TenantAtlas/specs/132-guid-context-resolver/plan.md
ahmido 8ee1174c8d feat: add resolved reference presentation layer (#161)
## 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
2026-03-10 18:52:52 +00:00

20 KiB
Raw Blame History

Implementation Plan: GUID Context Resolver & Human-Readable Reference Presentation

Branch: 132-guid-context-resolver | Date: 2026-03-10 | Spec: 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)

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)

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 todays 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.