## Summary - add a shared cross-resource navigation layer with canonical navigation context and related-context rendering - wire findings, policy versions, baseline snapshots, backup sets, and canonical operations surfaces into consistent drill-down flows - extend focused Pest coverage for canonical operations links, related navigation, and tenant-context preservation ## Testing - focused Pest coverage for spec 131 was added and the task list marks the implementation verification and Pint steps as completed ## Follow-up - manual QA checklist item `T036` in `specs/131-cross-resource-navigation/tasks.md` is still open and should be completed during review Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #160
7.8 KiB
Research: Cross-Resource Navigation & Drill-Down Cohesion
Feature: 131-cross-resource-navigation | Date: 2026-03-10
R1: Canonical operations links should continue through the existing tenantless route family
Decision: Reuse OperationRunLinks and the tenantless operations route family as the authoritative destination for all in-scope run-related drill-downs.
Rationale: The codebase already converges canonical run detail through route('admin.operations.view'), OperationRunLinks::tenantlessView(), and TenantlessOperationRunViewer. OperationRunLinks::view() already normalizes tenant-context callers onto the tenantless route, and the operations page preserves context through OperateHubShell instead of separate route families. Extending this pattern is lower-risk than creating new destination helpers or permitting direct resource-specific run routes to spread further.
Alternatives considered:
- Let each resource continue generating run URLs inline: rejected because route drift is already present and the spec explicitly targets canonical-route consistency.
- Reintroduce tenant-bound run detail URLs for convenience: rejected because spec 078 already moved operations toward workspace-level canonical routes.
R2: Relation mapping must move out of individual resources and into a shared support layer
Decision: Introduce a shared navigation presentation layer that resolves related-context entries, drill-down actions, labels, and unavailable states outside individual Filament resources.
Rationale: Current relation behavior is fragmented across FindingResource, BackupItemsRelationManager, PolicyResource relation managers, widgets, and OperationRunLinks. That fragmentation is precisely what the feature is trying to end. The product already uses support-layer abstractions for RBAC enforcement, action-surface rules, and badge semantics; a similar support-layer abstraction is the most consistent place for cross-resource relation logic.
Alternatives considered:
- Keep relation logic inside each resource and standardize only labels: rejected because labels alone do not solve availability, canonical target, or missing-state drift.
- Put all relation mapping inside Blade partials: rejected because authorization, route selection, and testability belong above the view layer.
R3: Detail-page related context should be implemented as structured infolist sections plus header actions
Decision: Add related context to key detail pages through infolist sections and predictable header or inline actions, not bespoke one-off widgets.
Rationale: The in-scope resources already use sectioned infolist-based detail pages, and Filament v5 documents header actions and view-page infolist testing as the intended extension points. This matches the constitution’s UX-001 requirement and keeps detail pages consistent with existing read-only resource patterns.
Alternatives considered:
- Use custom Blade page headers or embedded dashboards for every resource: rejected because it increases implementation variance and makes action testing harder.
- Put all related links only in header actions: rejected because the spec requires a structured related-context section, not just header buttons.
R4: List-level navigation should prioritize inspect affordance and a small visible action set
Decision: Use existing inspect affordances plus a small number of visible row-level related actions, with no more than the most relevant journeys exposed inline.
Rationale: Filament v5 supports clickable rows via recordUrl(), and the repo’s action-surface contract already requires an inspection affordance and discourages noisy row-action layouts. The spec’s goal is coherent workflows, not maximal link density. That means keeping the primary record-open action obvious, then surfacing one or two high-value related actions where they materially reduce dead ends.
Alternatives considered:
- Expose every related destination on each row: rejected because it creates link sprawl and undermines scannability.
- Move all related navigation to detail pages only: rejected because the spec explicitly calls for standard drill-down actions on important list screens.
R5: Authorization-aware link rendering should rely on target policies and entitlement checks, not optimistic links
Decision: Generate actionable related links only when the current user is entitled to the target resource; otherwise render a clear unavailable state only when awareness of the relation is allowed.
Rationale: OperationRunPolicy already enforces the required 404 vs 403 semantics, and FindingPolicy plus tenant membership checks show that tenant-entitlement is a hard visibility boundary. The UI cannot safely assume a visible relation implies an accessible destination. The new navigation layer therefore has to treat authorization as part of relation resolution, not as a last-second target-page failure.
Alternatives considered:
- Render the link and rely on the destination page to fail: rejected because it creates trust-damaging UX and can leak too much about inaccessible records.
- Hide all inaccessible relations entirely: rejected because the spec allows graceful non-clickable unavailable states where policy permits relation awareness.
R6: Breadcrumb and back behavior should follow explicit contextual navigation, not browser-history heuristics
Decision: Use explicit contextual back links and canonical lineage semantics, following the existing operations pages’ Back to ... and Show all ... patterns.
Rationale: TenantlessOperationRunViewer and Monitoring\Operations already implement explicit context-aware back actions rather than trusting browser history. That existing pattern is the right precedent for Spec 131 because the problem statement calls out mental-model failures caused by history-dependent back behavior.
Alternatives considered:
- Depend on browser history or referrer to preserve origin: rejected because it is fragile and opaque.
- Force every destination to rebuild the exact originating filtered list state: rejected because it over-scopes the feature into full navigation-state persistence.
R7: The first implementation slice should target the resources with the strongest existing evidence and test coverage
Decision: Prioritize Finding, BaselineSnapshot, PolicyVersion, BackupSet, and canonical operations surfaces first, while treating Policy and BaselineProfile as supporting parents in the same matrix.
Rationale: These resources already have dense existing test neighborhoods, clear operator workflows, and visible pain points around run links, source evidence, and related record traversal. Starting here yields the highest workflow value while staying incremental.
Alternatives considered:
- Attempt to align every possible related resource in one pass: rejected because the spec explicitly permits incremental rollout and warns against IA over-scope.
- Start from lower-value supporting resources first: rejected because it delays the highest operator-impact journeys.
R8: Contract artifact should model the shared navigation payload, not invent new APIs
Decision: Publish an internal OpenAPI artifact that formalizes the shared related-navigation payload and rule schemas without defining new HTTP endpoints.
Rationale: This feature does not add backend APIs; it standardizes UI-side navigation and related-context generation across existing Filament pages. A components-focused OpenAPI document still provides a formal contract for the presentation layer without pretending the feature introduces new REST resources.
Alternatives considered:
- Omit a contract artifact entirely: rejected because the planning workflow requires contracts output.
- Invent new HTTP endpoints purely to satisfy the planning template: rejected because that would distort the feature scope and mislead future implementation.