TenantAtlas/specs/131-cross-resource-navigation/plan.md
2026-03-10 17:05:07 +01:00

248 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Cross-Resource Navigation & Drill-Down Cohesion
**Branch**: `131-cross-resource-navigation` | **Date**: 2026-03-10 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/131-cross-resource-navigation/spec.md`
## Summary
Unify cross-resource navigation across governance, inventory, backup, and monitoring surfaces by introducing a shared relation-navigation presentation layer, standardizing canonical operations links through the existing tenantless operations route family, and adding predictable related-context sections plus limited drill-down actions on the highest-value resource pages. The implementation stays read-only, reuses existing Filament resources and policies, preserves workspace and tenant isolation, and concentrates first on findings, baseline snapshots, policy versions, backup sets, and canonical operations.
## 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 session-backed workspace and tenant context
**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 canonical workspace-level operations routes under `/admin/operations...`
**Project Type**: Laravel monolith / Filament web application
**Performance Goals**: Related-context rendering remains DB-only at page render time, uses bounded eager-loaded relations, adds no new uncontrolled polling, and keeps canonical operations routing free of duplicate route families
**Constraints**: No schema changes, no new Graph calls, no new operational side effects, no raw capability strings, no ad hoc URLs sprinkled across resources, preserve 404 vs 403 semantics, and keep link noise capped to the most relevant operator journeys
**Scale/Scope**: One shared navigation abstraction, one explicit navigation matrix, five primary resource families plus canonical operations surfaces, and focused regression coverage for navigation visibility, authorization, canonical routing, and unavailable states
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
- Inventory-first: PASS — the feature changes navigation and presentation only; inventory, snapshots, and backups remain distinct persisted concepts.
- Read/write separation: PASS — no new write flow is introduced; the feature adds read-only navigation and context affordances only.
- Graph contract path: PASS — no Microsoft Graph calls are added.
- Deterministic capabilities: PASS — link visibility and availability can be derived from existing capability resolvers and policies.
- RBAC-UX planes and isolation: PASS — the feature spans workspace-admin `/admin` and tenant-context `/admin/t/{tenant}/...` entry points but preserves canonical workspace-level operations destinations, 404 for non-members, and 403 for in-scope capability denial.
- Workspace isolation: PASS — workspace membership remains the visibility boundary for workspace-admin and canonical operations surfaces.
- RBAC-UX destructive confirmation: PASS / N/A — no new destructive actions are introduced.
- RBAC-UX global search: PASS — no new global-searchable resource is introduced; touched resources either already have view pages or are explicitly not globally searchable.
- Tenant isolation: PASS — tenant-owned resource links must be tenant-entitlement checked before rendering actionable destinations.
- Run observability: PASS / N/A — existing `OperationRun` records are reused as destinations only; no new runs or lifecycle transitions are introduced.
- Ops-UX 3-surface feedback: PASS / N/A — no new operation start surface or completion behavior is added.
- Ops-UX lifecycle and summary counts: PASS / N/A — no `OperationRun` status or outcome mutation occurs in this feature.
- 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 — related context and drill-down metadata remain DB-derived and should expose only already-authorized operator-facing labels.
- Badge semantics (BADGE-001): PASS — any context or availability badges introduced by the related-context pattern must use existing centralized badge semantics.
- UI naming (UI-NAMING-001): PASS — the spec standardizes operator-facing labels around `View ...` and `Open ...` vocabulary and avoids implementation-first terms.
- Filament UI Action Surface Contract: PASS — touched resources already have view/list surfaces; the feature will upgrade inspect affordances and related actions without introducing action sprawl or lone non-canonical view buttons.
- Filament UI UX-001: PASS — related context will be added through sectioned infolist or view-page layouts rather than ad hoc text fields.
- Filament v5 / Livewire v4 compliance: PASS — the plan remains inside the existing Filament v5 / Livewire v4 admin and tenant panels.
- Provider registration (`bootstrap/providers.php`): PASS — no new panel provider is added; existing Filament providers remain registered in `bootstrap/providers.php`.
- Global search resource rule: PASS — `BaselineSnapshotResource`, `BaselineProfileResource`, and `OperationRunResource` explicitly disable global search; `PolicyResource`, `PolicyVersionResource`, `FindingResource`, and `BackupSetResource` already expose view pages, so no new global-search dead end is introduced.
- Asset strategy: PASS — no new heavy asset bundle is required; current deployment behavior, including `php artisan filament:assets`, remains sufficient.
## Project Structure
### Documentation (this feature)
```text
specs/131-cross-resource-navigation/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── cross-resource-navigation.openapi.yaml
├── checklists/
│ └── requirements.md
└── tasks.md
```
### Source Code (repository root)
```text
app/
├── Filament/
│ ├── Pages/
│ │ ├── BaselineCompareLanding.php # baseline comparison landing with canonical run links
│ │ ├── Monitoring/
│ │ │ └── Operations.php # canonical operations index
│ │ └── Operations/
│ │ └── TenantlessOperationRunViewer.php # canonical run detail
│ ├── Resources/
│ │ ├── PolicyResource.php # tenant policy list/view + versions relation
│ │ ├── PolicyVersionResource.php # tenant policy version list/view
│ │ ├── BaselineProfileResource.php # workspace baseline profile list/view
│ │ ├── BaselineSnapshotResource.php # workspace baseline snapshot list/view
│ │ ├── FindingResource.php # tenant findings list/view
│ │ ├── BackupSetResource.php # tenant backup set list/view
│ │ ├── OperationRunResource.php # shared operations table/infolist config
│ │ └── BackupSetResource/
│ │ └── RelationManagers/
│ │ └── BackupItemsRelationManager.php # existing policy/version cross-links
│ └── Widgets/
│ └── Dashboard/ # existing recent findings/operations patterns
├── Policies/
│ ├── OperationRunPolicy.php # canonical run authorization semantics
│ └── FindingPolicy.php # tenant finding authorization semantics
├── Support/
│ ├── OperationRunLinks.php # current canonical operations URL helper
│ ├── OperateHub/ # tenant-context preservation patterns
│ ├── Rbac/ # UI enforcement helpers
│ └── Ui/
│ └── ActionSurface/ # action-surface contract helpers
routes/
└── web.php # canonical operations route definitions
resources/
└── views/
└── filament/ # existing infolist/page partials for read-only detail rendering
tests/
├── Feature/
│ ├── Filament/ # resource page and view-surface tests
│ ├── Findings/ # finding list/view behavior tests
│ ├── Monitoring/ # canonical operations route tests
│ ├── Operations/ # tenantless run viewer tests
│ └── Rbac/ # capability-aware UI enforcement tests
└── Unit/
├── Baselines/ # existing snapshot/policy resolver tests
└── Support/ # new navigation resolver / link builder tests
```
**Structure Decision**: Keep the feature inside the existing Laravel/Filament monolith. Implement a shared support-layer navigation abstraction beside `OperationRunLinks` and the existing UI support helpers, then wire it into the current resource list and view surfaces rather than introducing new panels, routes, or data stores.
## Complexity Tracking
> No Constitution Check violations. No justifications needed.
| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| — | — | — |
## Phase 0 — Research (DONE)
Output:
- `specs/131-cross-resource-navigation/research.md`
Key findings captured:
- Canonical operations routing already exists through `route('admin.operations.view')`, `TenantlessOperationRunViewer`, and `OperationRunLinks`, but related deep links are still scattered across individual resources and widgets.
- Existing resources already expose a mix of infolist sections, row actions, relation managers, and `recordUrl()` patterns; the gap is consistency, not missing primitives.
- Existing policies already model the required 404 vs 403 semantics, so link generation must be capability-aware rather than optimistic.
- The action-surface contract and Filament guidance both favor explicit inspect affordances and limited visible row actions, which aligns with the specs dead-end reduction and anti-link-sprawl goals.
- The highest-value initial resource set already has focused test neighborhoods, making incremental rollout practical.
## Phase 1 — Design & Contracts (DONE)
Outputs:
- `specs/131-cross-resource-navigation/data-model.md`
- `specs/131-cross-resource-navigation/contracts/cross-resource-navigation.openapi.yaml`
- `specs/131-cross-resource-navigation/quickstart.md`
Design highlights:
- Introduce a reusable related-navigation presentation model instead of continuing to build URLs and labels inline inside each resource.
- Keep `OperationRunLinks` as the canonical operations route helper, but expand the surrounding design so non-operation resources feed into it consistently.
- Add structured related-context sections to key view pages using existing infolist section patterns and explicit shared label vocabulary.
- Standardize list-level drill-down actions around a strict priority model: upstream evidence first, canonical run or operations context second, and filtered-list follow-up third, while keeping a primary inspect affordance plus at most two visible related actions.
- Preserve tenant context on canonical operations pages through explicit context hints or filter state, following the existing operate-hub shell patterns.
- Make breadcrumb and back-link lineage explicit on canonical operations surfaces so return navigation follows resource lineage or filtered-list origin rather than browser history guesswork.
## 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 navigation matrix and support layer
Goal: implement FR-131-15, FR-131-22, FR-131-23, and FR-131-24.
Changes:
- Add a centralized relation-mapping and presentation layer for related context entries, row actions, and canonical drill-down targets.
- Define the explicit matrix for Policy, PolicyVersion, BaselineSnapshot, BaselineProfile, Finding, BackupSet, and OperationRun relationships.
- Centralize shared operator-facing labels and unavailable-state reasons so resources do not diverge.
Tests:
- Add unit coverage for the relation resolver, label generation, availability states, and canonical-target selection.
### Step 2 — Standardize canonical operations links
Goal: implement FR-131-03, FR-131-04, FR-131-14, FR-131-20, and FR-131-21.
Changes:
- Refactor all in-scope “View run” and operations-related links to flow through `OperationRunLinks` and canonical operations routes.
- Align contextual back links, breadcrumb lineage, and tenant-context preservation with the existing `OperateHubShell` pattern.
- Remove or replace ad hoc direct route generation where equivalent canonical helper behavior exists.
Tests:
- Extend existing monitoring and operations tests to assert canonical route usage and tenant-context preservation.
- Add regression coverage proving tenant-specific non-canonical run links do not reappear on in-scope surfaces.
### Step 3 — Add structured related-context sections to key detail pages
Goal: implement FR-131-01, FR-131-02, FR-131-05, FR-131-06, FR-131-10, FR-131-16, FR-131-17, FR-131-18, and FR-131-19.
Changes:
- Add a structured related-context section to Finding, BaselineSnapshot, PolicyVersion, BackupSet, and canonical OperationRun detail surfaces.
- Use human-readable labels first, technical identifiers second, and explicit unavailable states where relations cannot be opened.
- Prefer infolist sections or view-page header actions over custom one-off Blade logic where existing resource patterns suffice.
- Prove future extensibility by keeping new relation types matrix-driven through the shared label catalog and related-context renderer rather than resource-specific branching.
Tests:
- Add feature coverage proving the expected related context renders on key detail pages when relations exist.
- Add negative-path coverage for missing or unauthorized related targets.
### Step 4 — Add standard list-level drill-down actions
Goal: implement FR-131-07, FR-131-08, FR-131-09, and FR-131-10.
Changes:
- Add or normalize row-level related actions on findings, policy versions, backup sets, and relevant operations lists.
- Preserve each tables inspect affordance while capping visible row actions and pushing overflow into grouped actions only when genuinely needed.
- Replace raw ID or count-only relation renderings with accessible drill-down labels where operationally important.
Tests:
- Add Filament list tests asserting related row actions appear only when relevant and stay hidden or disabled when access is not allowed.
- Add regression coverage for action vocabulary consistency on in-scope list surfaces.
### Step 5 — Wire graceful unavailable states and authorization-aware rendering
Goal: implement FR-131-11, FR-131-12, and FR-131-13.
Changes:
- Ensure relation resolvers can distinguish missing, unresolved, and unauthorized states.
- Render non-clickable unavailable states only when policy allows awareness of the relation.
- Preserve server-side target authorization through existing policies and UI enforcement helpers.
Tests:
- Add positive and negative authorization coverage proving non-members get 404 semantics, members without capability get 403 at the destination, and unavailable states do not leak protected detail.
### Step 6 — Finalize rollout, docs-in-code consistency, and regression safety
Goal: implement the remaining acceptance criteria and protect the pattern from drift.
Changes:
- Audit in-scope resources for leftover raw IDs, inconsistent labels, and direct route generation.
- Ensure canonical operations links, related-context sections, and row actions follow the explicit matrix rather than page-by-page exceptions.
- Keep rollout incremental, starting with findings, snapshots, policy versions, and operations before extending to backup sets and the remaining aligned surfaces.
Tests:
- Run focused Pest suites for findings, monitoring, operations, baselines, policies, and backup UI surfaces.
- Run Sail-based Pint on dirty files during implementation.
## Constitution Check (Post-Design)
Re-check result: PASS.
- Livewire v4.0+ compliance: preserved because the design remains inside the existing Filament v5 / Livewire v4 application surfaces.
- Provider registration location: unchanged; existing panel providers remain registered in `bootstrap/providers.php`.
- Globally searchable resources: `BaselineSnapshotResource`, `BaselineProfileResource`, and `OperationRunResource` keep global search disabled; `PolicyResource`, `PolicyVersionResource`, `FindingResource`, and `BackupSetResource` already have view pages, so no new global-search dead end is created.
- Destructive actions: no new destructive actions are added by this feature; existing destructive actions remain subject to `->requiresConfirmation()` and current authorization rules.
- Asset strategy: no new heavy assets are introduced; existing Filament assets remain sufficient, and deploy-time `php artisan filament:assets` behavior is unchanged.
- Testing plan: add focused Pest feature coverage for related-context rendering, canonical operations links, list-level drill-down actions, unavailable states, and authorization-aware visibility, plus unit tests for the shared relation-mapping and presentation layer.