## Summary - add the shared resolved-reference foundation with registry, resolvers, presenters, and badge semantics - refactor related context, assignment evidence, and policy-version assignment rendering toward label-first reference presentation - add Spec 132 artifacts and focused Pest coverage for reference resolution, degraded states, canonical linking, and tenant-context carryover ## Verification - `vendor/bin/sail bin pint --dirty --format agent` - focused Pest verification was marked complete in the task artifact ## Notes - this PR is opened from the current session branch - `specs/132-guid-context-resolver/tasks.md` reflects in-progress completion state for the implemented tasks Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #161
261 lines
20 KiB
Markdown
261 lines
20 KiB
Markdown
# Implementation Plan: GUID Context Resolver & Human-Readable Reference Presentation
|
||
|
||
**Branch**: `132-guid-context-resolver` | **Date**: 2026-03-10 | **Spec**: [spec.md](./spec.md)
|
||
**Input**: Feature specification from `/specs/132-guid-context-resolver/spec.md`
|
||
|
||
## Summary
|
||
|
||
Replace GUID-first reference display on core enterprise surfaces by extending the existing shared related-context/navigation work into a broader reference-resolution foundation. The implementation will introduce explicit reference descriptor and resolved-reference contracts, a resolver registry for internal and provider-backed references, and shared compact/detail rendering patterns so findings, baseline snapshots, operation runs, assignments, and related-context sections show names first, type and state second, and technical IDs only as secondary evidence.
|
||
|
||
## 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 plus existing workspace and tenant context, existing Eloquent relations, and provider-derived identifiers already stored in domain records
|
||
**Testing**: Pest v4 feature and unit tests on PHPUnit 12
|
||
**Target Platform**: Laravel Sail web application with workspace-admin routes under `/admin`, tenant-context routes under `/admin/t/{tenant}/...`, and shared Filament infolist/table rendering patterns
|
||
**Project Type**: Laravel monolith / Filament web application
|
||
**Performance Goals**: Reference rendering remains DB-only at page render time, uses bounded eager loading and batched local lookups, introduces no render-time Graph/provider calls, and avoids new N+1 patterns on dense list surfaces
|
||
**Constraints**: No schema changes, no new Graph calls, no unauthorized existence leakage, no page-specific fallback logic for supported classes, no broken pages when a resolver is missing, preserve 404 vs 403 semantics, and keep technical IDs visibly secondary
|
||
**Scale/Scope**: One shared resolver registry and value-object model, 8 to 10 initial reference classes, compact plus detailed presentation variants, 5 primary target surface families, and focused regression coverage for state rendering, linking, and authorization-aware degradation
|
||
|
||
## Constitution Check
|
||
|
||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||
|
||
- Inventory-first: PASS — the feature changes reference presentation only; inventory, snapshot, and backup persistence semantics remain unchanged.
|
||
- Read/write separation: PASS — no write flow or new mutation is introduced; the feature is read-only UI and support-layer work.
|
||
- Graph contract path: PASS — no new Microsoft Graph calls are introduced, and reference resolution must stay DB-only or source-context-only at render time.
|
||
- Deterministic capabilities: PASS — linkability and degraded-state behavior can be derived from existing gates, policies, capability registries, and current route helpers.
|
||
- RBAC-UX planes and isolation: PASS — the feature spans workspace-admin `/admin` and tenant-context `/admin/t/{tenant}/...` surfaces but must preserve 404 for non-members and 403 for in-scope capability denial.
|
||
- Workspace isolation: PASS — workspace membership remains the visibility boundary for workspace-level reference labels and canonical destinations.
|
||
- RBAC-UX destructive confirmation: PASS / N/A — the feature introduces no destructive actions.
|
||
- RBAC-UX global search: PASS — touched resources either already have view pages or explicitly disable global search; the feature must not create new search dead ends.
|
||
- Tenant isolation: PASS — tenant-owned references must enforce current tenant entitlement before exposing protected labels or links.
|
||
- Run observability: PASS / N/A — existing `OperationRun` records may be displayed as resolved references, but no new run creation or lifecycle mutation occurs.
|
||
- Ops-UX 3-surface feedback: PASS / N/A — no new operation-start or completion flow is introduced.
|
||
- Ops-UX lifecycle and summary counts: PASS / N/A — no `OperationRun.status` or `OperationRun.outcome` transitions are introduced.
|
||
- Ops-UX guards and system runs: PASS / N/A — existing operations behavior remains unchanged.
|
||
- Automation: PASS / N/A — no queued or scheduled workflow changes are required.
|
||
- Data minimization: PASS — reference presentation uses already-authorized labels, IDs, and source hints only; no secrets or raw payload dumps are introduced.
|
||
- Badge semantics (BADGE-001): PASS — if reference-state badges are added or refined, they must map through `app/Support/Badges/BadgeCatalog.php` and `app/Support/Badges/BadgeRenderer.php` instead of page-specific label/color logic.
|
||
- UI naming (UI-NAMING-001): PASS — operator-facing reference copy remains domain-first, such as “Policy,” “Baseline snapshot,” “Operation run,” “Group,” or “Role definition,” and technical ID terminology stays secondary.
|
||
- UI naming (UI-NAMING-001): PASS — operator-facing reference copy remains domain-first, such as “Policy,” “Baseline snapshot,” “Operation run,” “Group,” or “Role definition,” and technical ID terminology stays secondary across labels, helper text, link labels, empty states, and degraded-state copy.
|
||
- Filament UI Action Surface Contract: PASS — touched resources already expose list/view surfaces; the feature upgrades inspect affordances and related-context rows without introducing destructive or noisy action sprawl, and touched resources or relation managers must keep their `actionSurfaceDeclaration()` coverage current where applicable.
|
||
- Filament UI UX-001: PASS — modified detail pages will continue to use sectioned infolists or read-only layouts, while list surfaces keep search/sort/filter behavior and adopt compact shared reference rendering.
|
||
- Filament v5 / Livewire v4 compliance: PASS — the plan remains inside the existing Filament v5 / Livewire v4 application surfaces.
|
||
- Provider registration (`bootstrap/providers.php`): PASS — no new panel provider is introduced; existing providers remain registered in `bootstrap/providers.php`.
|
||
- Global search resource rule: PASS — `FindingResource`, `PolicyVersionResource`, `BackupSetResource`, and `EntraGroupResource` already have view pages; workspace-level resources touched by the feature that are not globally searchable remain disabled.
|
||
- Asset strategy: PASS — no heavy frontend asset bundle is required; shared Blade partials and existing Filament assets are sufficient, and deploy-time `php artisan filament:assets` behavior remains unchanged.
|
||
|
||
## Project Structure
|
||
|
||
### Documentation (this feature)
|
||
|
||
```text
|
||
specs/132-guid-context-resolver/
|
||
├── plan.md
|
||
├── research.md
|
||
├── data-model.md
|
||
├── quickstart.md
|
||
├── contracts/
|
||
│ └── reference-presentation.openapi.yaml
|
||
├── checklists/
|
||
│ └── requirements.md
|
||
└── tasks.md
|
||
```
|
||
|
||
### Source Code (repository root)
|
||
|
||
```text
|
||
app/
|
||
├── Filament/
|
||
│ ├── Resources/
|
||
│ │ ├── FindingResource.php # existing related-context + list action consumer
|
||
│ │ ├── PolicyVersionResource.php # existing related-context + policy lineage consumer
|
||
│ │ ├── BackupSetResource.php # existing related-context + run linkage consumer
|
||
│ │ ├── OperationRunResource.php # canonical run detail consumer
|
||
│ │ ├── EntraGroupResource.php # current GUID-heavy directory reference surface
|
||
│ │ ├── BaselineProfileResource/
|
||
│ │ │ └── RelationManagers/
|
||
│ │ │ └── BaselineTenantAssignmentsRelationManager.php # concrete assignment-like target surface
|
||
│ │ └── BaselineSnapshotResource/
|
||
│ │ └── Pages/ViewBaselineSnapshot.php # snapshot detail related-context consumer
|
||
│ └── Widgets/
|
||
│ └── Dashboard/ # reference-heavy summary surfaces to keep aligned later
|
||
├── Models/
|
||
│ ├── Policy.php
|
||
│ ├── PolicyVersion.php
|
||
│ ├── BaselineProfile.php
|
||
│ ├── BaselineSnapshot.php
|
||
│ ├── BackupSet.php
|
||
│ ├── OperationRun.php
|
||
│ ├── Finding.php
|
||
│ ├── EntraGroup.php
|
||
│ ├── EntraRoleDefinition.php
|
||
│ └── Tenant.php
|
||
├── Services/
|
||
│ ├── Baselines/
|
||
│ │ └── SnapshotRendering/ # existing registry + DTO pattern to mirror
|
||
│ └── Directory/
|
||
│ └── EntraGroupLabelResolver.php # existing narrow provider-backed label resolver
|
||
├── Support/
|
||
│ ├── Navigation/
|
||
│ │ ├── CrossResourceNavigationMatrix.php # existing source/surface matrix
|
||
│ │ ├── RelatedNavigationResolver.php # existing entry-point to evolve or wrap
|
||
│ │ ├── RelatedContextEntry.php # current shallow view payload model
|
||
│ │ └── CanonicalNavigationContext.php # canonical link context helper
|
||
│ ├── OperationRunLinks.php # canonical run route helper
|
||
│ └── References/ # NEW shared reference descriptor/registry/value objects
|
||
resources/
|
||
└── views/
|
||
└── filament/
|
||
└── infolists/
|
||
└── entries/
|
||
├── related-context.blade.php # current reusable related-context renderer
|
||
└── resolved-reference*.blade.php # NEW compact/detail variants
|
||
tests/
|
||
├── Feature/
|
||
│ ├── Filament/ # resource view/list rendering tests
|
||
│ ├── Monitoring/ # canonical operations link tests
|
||
│ └── Rbac/ # authorization-aware visibility/degradation tests
|
||
└── Unit/
|
||
├── Support/
|
||
│ └── References/ # NEW resolver registry / DTO / state tests
|
||
└── Services/
|
||
└── Directory/ # existing label resolver tests that may be upgraded
|
||
```
|
||
|
||
**Structure Decision**: Keep the feature inside the existing Laravel/Filament monolith and extend the current shared navigation support rather than creating a parallel page-only solution. Introduce a dedicated reference-resolution layer under `app/Support/References`, then adapt the current `RelatedNavigationResolver`, related-context partials, and target resources to consume the richer reference semantics.
|
||
|
||
## Complexity Tracking
|
||
|
||
> No Constitution Check violations. No justifications needed.
|
||
|
||
| Violation | Why Needed | Simpler Alternative Rejected Because |
|
||
|-----------|------------|-------------------------------------|
|
||
| — | — | — |
|
||
|
||
## Phase 0 — Research (DONE)
|
||
|
||
Output:
|
||
- `specs/132-guid-context-resolver/research.md`
|
||
|
||
Key findings captured:
|
||
- The repo already has a first-generation shared navigation layer through `RelatedNavigationResolver`, `CrossResourceNavigationMatrix`, `RelatedContextEntry`, and the shared `related-context` Blade partial, but that layer models only availability plus links, not explicit descriptor classes, multi-state resolution, or controlled technical detail presentation.
|
||
- `BaselineSnapshotPresenter`, `SnapshotTypeRendererRegistry`, and the rendered snapshot DTOs show a strong existing pattern for registry-driven resolution with immutable value objects and fallback behavior, which maps well to a shared reference resolver registry.
|
||
- `EntraGroupLabelResolver` proves provider-backed label enrichment is already needed, but today it collapses unresolved and resolved references into a single label string instead of returning structured reference states.
|
||
- `OperationRunLinks` and existing resource `getUrl()` helpers already encode canonical destinations, so Spec 132 should centralize richer label/state handling around those helpers instead of inventing new route families.
|
||
- Filament v5 supports custom `ViewEntry` renderers and rich table layouts, so compact and detailed reference variants can remain shared without publishing internal Filament views or introducing a heavy frontend rewrite.
|
||
- The highest-value target surfaces already expose related-context sections or reference-heavy infolist/table entries, making incremental adoption practical without a schema migration.
|
||
|
||
## Phase 1 — Design & Contracts (DONE)
|
||
|
||
Outputs:
|
||
- `specs/132-guid-context-resolver/data-model.md`
|
||
- `specs/132-guid-context-resolver/contracts/reference-presentation.openapi.yaml`
|
||
- `specs/132-guid-context-resolver/quickstart.md`
|
||
|
||
Design highlights:
|
||
- Introduce `ReferenceDescriptor`, `ResolvedReference`, `ReferenceLinkTarget`, `ReferenceTechnicalDetail`, `ReferencePresentationVariant`, and a `ReferenceResolverRegistry` as the canonical shared contracts for reference semantics.
|
||
- Keep reference resolution DB-only and best-effort at render time by combining existing relations, local model lookups, stored source metadata, and narrow provider-backed label resolvers such as `EntraGroupLabelResolver`; no external provider call is allowed during page render.
|
||
- Extend or wrap the current `RelatedNavigationResolver` so it produces richer reference payloads instead of today’s shallow `value + secondaryValue + availability` model.
|
||
- Preserve canonical destinations through existing helpers like `OperationRunLinks` and resource `getUrl()` methods while making linkability capability-aware and non-ambiguous.
|
||
- Add shared compact and detailed reference renderers so list rows and detail sections preserve the same semantic order even when the visual density differs, and map reference-state badges through the shared badge system.
|
||
- Add shared compact and detailed reference renderers so list rows and detail sections preserve the same semantic order even when the visual density differs, map reference-state badges through the shared badge system, and preserve domain-consistent operator copy.
|
||
- Roll out incrementally by first covering internal model-backed references, then security/provider-backed references, and finally upgrading existing related-context sections and table cells on the target surfaces.
|
||
|
||
## 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 — Define the shared reference contracts and registry
|
||
|
||
Goal: implement FR-132-02, FR-132-03, FR-132-05, FR-132-16, and FR-132-23.
|
||
|
||
Changes:
|
||
- Add the shared descriptor, state, technical-detail, and resolved-reference value objects.
|
||
- Add a registry or dispatcher that maps explicit reference classes to concrete resolvers.
|
||
- Define a fallback resolver for unsupported or unresolved classes that still keeps the reference visible.
|
||
|
||
Tests:
|
||
- Add unit coverage for registry dispatch, unsupported-class fallback, value-object normalization, and reference-state serialization.
|
||
|
||
### Step 2 — Implement the initial model-backed resolvers
|
||
|
||
Goal: implement FR-132-01, FR-132-04, FR-132-09, FR-132-10, FR-132-13, and FR-132-21.
|
||
|
||
Changes:
|
||
- Add resolvers for policies, policy versions, baseline profiles, baseline snapshots, operation runs, and backup sets.
|
||
- Resolve primary labels, type/context labels, canonical targets, and secondary technical details from local records and already-known relationships.
|
||
- Batch or eager-load where needed so detail and list surfaces avoid N+1 lookups.
|
||
|
||
Tests:
|
||
- Add unit coverage for each core resolver, including resolved, partially resolved, missing, and unsupported cases.
|
||
|
||
### Step 3 — Implement governance, security, and provider-backed resolvers
|
||
|
||
Goal: implement FR-132-04, FR-132-08, FR-132-10, FR-132-14, and FR-132-28.
|
||
|
||
Changes:
|
||
- Add resolvers for role definitions, Entra groups, principal-like references, assignment targets, and tenant-linked external object references that are already surfaced today.
|
||
- Upgrade narrow helpers like `EntraGroupLabelResolver` into structured resolver collaborators instead of raw label string formatters.
|
||
- Differentiate inaccessible, unresolved, deleted or missing, and external-only limited-context states explicitly.
|
||
|
||
Tests:
|
||
- Add unit coverage for provider-backed label reuse, inaccessible-state degradation, fallback labels, and deleted-object behavior.
|
||
|
||
### Step 4 — Create shared presentation variants and state vocabulary
|
||
|
||
Goal: implement FR-132-06, FR-132-07, FR-132-08, FR-132-12, FR-132-18, FR-132-19, and FR-132-20.
|
||
|
||
Changes:
|
||
- Add compact and detailed shared reference renderers for infolists, related-context sections, and dense tables.
|
||
- Keep the visual order consistent: label first, type/context second, state next, technical ID last.
|
||
- Centralize state badges and unavailable-state copy instead of letting each resource improvise labels.
|
||
|
||
Tests:
|
||
- Add feature coverage proving technical IDs stay secondary, unresolved states remain visible, and clickable vs non-clickable rendering is unambiguous.
|
||
|
||
### Step 5 — Refactor target surfaces to consume the shared reference layer
|
||
|
||
Goal: implement FR-132-15, FR-132-24, FR-132-25, FR-132-26, and FR-132-27.
|
||
|
||
Changes:
|
||
- Refactor findings, baseline snapshots, operation runs, policy versions, backup sets, the baseline tenant assignments relation manager, and assignment-evidence sections on finding, policy-version, and baseline-snapshot surfaces to use the shared resolver/presentation layer.
|
||
- Replace GUID-heavy infolist/table fields and ad hoc related-context arrays with structured resolved references.
|
||
- Ensure existing canonical links continue to flow through `OperationRunLinks` and resource route helpers while touched Filament resources preserve explicit inspect affordances, row-action caps, and documented exemptions.
|
||
- Ensure tenant-context entry into canonical workspace destinations preserves visible originating-tenant meaning via filters, context badges, or source-context metadata where relevant.
|
||
|
||
Tests:
|
||
- Add or update Filament feature coverage for findings, baseline snapshots, operation runs, and assignment-like surfaces to prove label-first rendering and canonical links.
|
||
|
||
### Step 6 — Enforce authorization-aware degradation and regression safety
|
||
|
||
Goal: implement FR-132-11, FR-132-14, FR-132-17, FR-132-22, and the acceptance criteria around safe degradation.
|
||
|
||
Changes:
|
||
- Ensure the shared layer differentiates non-member 404 semantics from in-scope capability denial and never leaks protected labels where policy forbids it.
|
||
- Keep unsupported or partially known references visible without breaking pages.
|
||
- Audit touched resources for remaining GUID-first output and remove page-specific formatting branches for supported classes.
|
||
- Lock the rollout boundary so the surfaces named in the spec fully adopt the shared pattern now, while dashboard summary widgets and other out-of-scope views are explicitly allowed to remain on older formatting until a later spec.
|
||
- Add regression coverage for domain-consistent operator copy and tenant-context carryover on migrated canonical destinations.
|
||
|
||
Tests:
|
||
- Add positive and negative authorization coverage proving inaccessible references are non-clickable, protected destinations stay guarded, and unsupported resolvers do not hide the underlying reference.
|
||
- Add regression coverage preventing raw GUIDs from reappearing as the primary visible value on supported target surfaces.
|
||
|
||
## Constitution Check (Post-Design)
|
||
|
||
Re-check result: PASS.
|
||
|
||
- Livewire v4.0+ compliance: preserved because the design stays inside the existing Filament v5 / Livewire v4 surfaces.
|
||
- Provider registration location: unchanged; existing panel providers remain registered in `bootstrap/providers.php`.
|
||
- Globally searchable resources: touched searchable resources already expose view pages, and non-searchable resources remain explicitly disabled, so the Filament global-search rule remains satisfied.
|
||
- Destructive actions: no new destructive actions are introduced; existing destructive behavior remains subject to current confirmation and authorization rules.
|
||
- Asset strategy: no new heavy assets are introduced; shared Blade partials and existing Filament view infrastructure are sufficient, and deploy-time `php artisan filament:assets` behavior remains unchanged.
|
||
- Testing plan: add focused Pest unit coverage for registry dispatch, resolver behavior, shared badge mapping, state normalization, and authorization-aware link generation, plus focused Filament feature coverage for findings, baseline snapshots, operation runs, the baseline tenant assignments relation manager, assignment-evidence surfaces, tenant-context carryover on canonical destinations, domain-consistent copy, and degraded-reference rendering.
|