# Phase 0 Research: GUID Context Resolver & Human-Readable Reference Presentation ## Decision 1: Extend the existing shared navigation layer instead of replacing it - Decision: Build the new reference semantics on top of the current shared related-context/navigation foundation rather than starting from a second unrelated abstraction. - Rationale: The codebase already has `RelatedNavigationResolver`, `CrossResourceNavigationMatrix`, `RelatedContextEntry`, shared related-context Blade rendering, and canonical route helpers. Reusing those extension points reduces migration risk and keeps Spec 131 and Spec 132 aligned. - Alternatives considered: - Replace the navigation layer entirely with a new reference-only stack: rejected because it would duplicate route, availability, and action-label logic that already exists and is already wired into multiple resources. - Keep page-level arrays and only restyle the Blade partial: rejected because it would not satisfy the spec’s requirement for explicit reference classes, shared semantics, and distinct degraded states. ## Decision 2: Model references through explicit input and output contracts - Decision: Introduce a structured `ReferenceDescriptor` input contract and a normalized `ResolvedReference` output contract with explicit state, type, label, technical detail, and optional canonical target. - Rationale: The current `RelatedContextEntry` payload is useful for immediate rendering but too shallow for the broader semantics required here. A descriptor plus resolved-reference pair makes support for partial resolution, unsupported classes, and future providers predictable and testable. - Alternatives considered: - Continue passing free-form arrays between resources and partials: rejected because it invites page-specific drift and makes regression testing weak. - Resolve everything directly inside Blade partials: rejected because presentation should not own resolution logic or authorization decisions. ## Decision 3: Keep render-time resolution DB-only and best-effort - Decision: Resolve references at render time using existing relations, local model lookups, current workspace or tenant context, stored fallback labels, and existing helper services only; do not make live Microsoft Graph or provider calls. - Rationale: The constitution and current architecture keep monitoring and governance views DB-only at render time. Best-effort local resolution is sufficient for the target surfaces and avoids latency, availability, and authorization leakage problems. - Alternatives considered: - Make on-demand provider calls to improve labels: rejected because it violates the DB-only rendering expectation, adds latency, and complicates authorization. - Cache external labels aggressively in new tables: rejected because the spec explicitly avoids introducing new persistent models solely for resolution. ## Decision 4: Use two shared presentation variants with one semantic payload - Decision: Provide a compact variant for dense tables and a detailed variant for related-context or infolist sections, both powered by the same resolved-reference payload. - Rationale: Some target surfaces are list-dense and cannot absorb a full detail block without becoming noisy, while detail pages need more explanatory context and degraded-state messaging. One semantic contract with two renderers keeps the hierarchy stable while fitting each surface. - Alternatives considered: - Force one heavy component everywhere: rejected because it would make list screens noisy and reduce scanability. - Allow each page to design its own variant independently: rejected because it would recreate the inconsistency the spec is meant to solve. ## Decision 5: Authorization controls linkability first, label disclosure second - Decision: Canonical targets become actionable only when current policy allows access; label and state disclosure must degrade to inaccessible or unresolved only to the extent policy allows. - Rationale: The product’s 404-vs-403 semantics and deny-as-not-found rules are already explicit. The reference layer must not accidentally leak object existence or friendly labels just because it has enough data to resolve them internally. - Alternatives considered: - Hide every unauthorized reference completely: rejected because some surfaces legitimately need to preserve the existence of a reference without allowing navigation. - Always show the resolved label even when navigation is forbidden: rejected because that can leak protected detail. ## Decision 6: Upgrade narrow label helpers into structured resolver collaborators - Decision: Existing helpers such as `EntraGroupLabelResolver` should become collaborators that feed structured resolution outputs rather than emitting final UI labels. - Rationale: Current helpers return a single string like `Name (…token)`, which is not enough to separate primary label, type/context, state, and technical detail. They remain useful, but inside a richer resolver contract. - Alternatives considered: - Leave helpers untouched and parse their formatted strings back into UI parts: rejected because it is brittle and loses state intent. - Rewrite all provider-backed label logic from scratch: rejected because the current local lookup behavior is already useful and should be preserved. ## Decision 7: Leverage the repo’s existing registry-and-DTO pattern - Decision: Mirror the `BaselineSnapshotPresenter` and `SnapshotTypeRendererRegistry` pattern by using immutable value objects, registry dispatch, and fallback behavior for references. - Rationale: The repo already favors registry-driven support layers for normalization and rendering. Following that pattern keeps the reference system familiar, testable, and consistent with current architecture. - Alternatives considered: - Put the entire resolution switch in one large service class: rejected because explicit per-class resolvers are easier to extend and test. - Encode resolution rules in configuration only: rejected because authorization-aware destination logic and best-effort lookup behavior require application code.