TenantAtlas/specs/085-tenant-operate-hub/tasks.md
ahmido 2bf5de4663 085-tenant-operate-hub (#103)
Summary

Consolidates the “Tenant Operate Hub” work (Spec 085) and the follow-up adjustments from the 086 session merge into a single branch ready to merge into dev.
Primary focus: stabilize Ops/Operate Hub UX flows, tighten/align authorization semantics, and make the full Sail test suite green.
Key Changes

Ops UX / Verification
Readonly members can view verification operation runs (reports) while starting verification remains restricted.
Normalized failure reason-code handling and aligned UX expectations with the provider reason-code taxonomy.
Onboarding wizard UX
“Start verification” CTA is hidden while a verification run is active; “Refresh” is shown during in-progress runs.
Treats provider_permission_denied as a blocking reason (while keeping legacy compatibility).
Test + fixture hardening
Standardized use of default provider connection fixtures in tests where sync/restore flows require it.
Fixed multiple Filament URL/tenant-context test cases to avoid 404s and reduce tenancy routing brittleness.
Policy sync / restore safety
Enrollment configuration type collision classification tests now exercise the real sync path (with required provider connection present).
Restore edge-case safety tests updated to reflect current provider-connection requirements.
Testing

vendor/bin/sail artisan test --compact (green)
vendor/bin/sail bin pint --dirty (green)
Notes

Includes merged 086 session work already (no separate PR needed).

Co-authored-by: Ahmed Darrazi <ahmeddarrazi@ebc83aaa-d947-4a08-b88e-bd72ac9645f7.fritz.box>
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box>
Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.fritz.box>
Reviewed-on: #103
2026-02-11 13:02:03 +00:00

193 lines
11 KiB
Markdown
Raw Permalink 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.

---
description: "Task list for Spec 085 — Tenant Operate Hub / Tenant Overview IA"
---
# Tasks: Spec 085 — Tenant Operate Hub / Tenant Overview IA
**Input**: Design documents from `/specs/085-tenant-operate-hub/`
**Required**:
- `specs/085-tenant-operate-hub/plan.md`
- `specs/085-tenant-operate-hub/spec.md`
**Additional docs present**:
- `specs/085-tenant-operate-hub/research.md`
- `specs/085-tenant-operate-hub/data-model.md`
- `specs/085-tenant-operate-hub/contracts/openapi.yaml`
- `specs/085-tenant-operate-hub/quickstart.md`
**Tests**: REQUIRED (runtime UX + security semantics; Pest)
---
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: Confirm the existing code touchpoints and test harness for Spec 085.
- [X] T001 Confirm canonical Monitoring routes + existing clear-context endpoint in routes/web.php and app/Http/Controllers/ClearTenantContextController.php
- [X] T002 Confirm the Monitoring pages exist and are canonical: app/Filament/Pages/Monitoring/Operations.php, app/Filament/Pages/Operations/TenantlessOperationRunViewer.php, app/Filament/Pages/Monitoring/Alerts.php, app/Filament/Pages/Monitoring/AuditLog.php
- [X] T003 Confirm Tenant panel provider is the entry point for tenant sidebar Monitoring shortcuts in app/Providers/Filament/TenantPanelProvider.php
- [X] T004 Confirm Laravel 11+/12 panel provider registration is in bootstrap/providers.php (not bootstrap/app.php)
- [X] T005 [P] Identify existing monitoring/tenant scoping tests to extend (tests/Feature/Monitoring/OperationsTenantScopeTest.php, tests/Feature/Operations/TenantlessOperationRunViewerTest.php)
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Shared helper behavior must match Spec 085 semantics before story work.
- [X] T006 Update scope-label copy and semantics in app/Support/OperateHub/OperateHubShell.php (MUST match FR-085-002 exactly: "Scope: Workspace — all tenants" / "Scope: Tenant — <tenant name>")
- [X] T007 Ensure OperateHubShell resolves active entitled tenant context safely (Filament tenant when present, otherwise remembered last-tenant id for the current workspace)
- [X] T008 Update OperateHubShell return affordance label to include tenant name ("Back to <tenant name>") in app/Support/OperateHub/OperateHubShell.php
- [X] T009 Add a helper method to resolve “active tenant AND still entitled” in app/Support/OperateHub/OperateHubShell.php (used by Operations index + run detail to implement stale-tenant-context behavior)
- [X] T010 Ensure Monitoring renders remain DB-only (no outbound calls / no side effects) by standardizing test guards with Http::preventStrayRequests() in tests/Feature/Spec085/*.php and existing coverage tests/Feature/Monitoring/OperationsTenantScopeTest.php and tests/Feature/Operations/TenantlessOperationRunViewerTest.php
**Checkpoint**: Shared semantics locked; user story work can begin.
---
## Phase 3: User Story 1 — Monitoring feels context-aware (Priority: P1) 🎯 MVP
**Goal**: When tenant context is active, Monitoring clearly shows tenant scope + deterministic “Back to tenant” and offers explicit “Show all tenants” to exit.
**Independent Test**: With tenant context active + entitled, GET `/admin/operations` shows `Scope: Tenant — <tenant>` and buttons `Back to <tenant>` and `Show all tenants`; clicking “Show all tenants” clears tenant context and returns to workspace-wide operations.
### Tests for User Story 1 (write first)
- [X] T011 [P] [US1] Add Spec 085 operations header tests in tests/Feature/Spec085/OperationsIndexHeaderTest.php (tenant scope label + both CTAs)
- [X] T012 [P] [US1] Add stale-tenant-context test in tests/Feature/Spec085/OperationsIndexHeaderTest.php (tenant context set but user not entitled → workspace scope + no tenant name + no back-to-tenant)
- [X] T013 [P] [US1] Add explicit-exit behavior test in tests/Feature/Spec085/OperationsIndexHeaderTest.php (POST /admin/clear-tenant-context clears Filament tenant + last tenant id)
- [X] T014 [P] [US1] Add tenant navigation shortcuts test in tests/Feature/Spec085/TenantNavigationMonitoringShortcutsTest.php (tenant sidebar shows “Monitoring” group with Runs/Alerts/Audit Log)
- [X] T015 [P] [US1] Add “deny-as-not-found” regression tests for canonical Monitoring access in tests/Feature/Spec085/DenyAsNotFoundSemanticsTest.php (non-workspace-member → 404 for /admin/operations and /admin/operations/{run})
- [X] T016 [P] [US1] Add “deny-as-not-found” regression test for tenant dashboard direct access in tests/Feature/Spec085/DenyAsNotFoundSemanticsTest.php (non-entitled to tenant → 404 for /admin/t/{tenant})
### Implementation for User Story 1
- [X] T017 [US1] Replace Tenant sidebar "Operations" item with "Monitoring" group shortcuts in app/Providers/Filament/TenantPanelProvider.php (Runs→/admin/operations, Alerts→/admin/alerts, Audit Log→/admin/audit-log)
- [X] T018 [US1] Implement Operations index scope indicator per Spec 085 in app/Filament/Pages/Monitoring/Operations.php (workspace vs tenant; stale context treated as workspace)
- [X] T019 [US1] Implement Operations index CTAs per Spec 085 in app/Filament/Pages/Monitoring/Operations.php (Back to <tenant> using App\Filament\Pages\TenantDashboard::getUrl(panel: 'tenant', tenant: $tenant); Show all tenants exits tenant context)
- [X] T020 [US1] Ensure “Show all tenants” uses an explicit server-side action (no implicit GET mutation) in app/Filament/Pages/Monitoring/Operations.php (perform the same mutations as app/Http/Controllers/ClearTenantContextController.php: Filament::setTenant(null, true) + WorkspaceContext::clearLastTenantId(); then redirect to /admin/operations)
**Checkpoint**: US1 fully testable and meets FR-085-001/002/005/007/010.
---
## Phase 4: User Story 2 — Canonical URLs with explicit scope (Priority: P2)
**Goal**: Canonical Monitoring URLs never implicitly change tenant context; tenant context may only affect default filtering and must be obvious.
**Independent Test**: With tenant context active, GET `/admin/operations` does not change tenant context and defaults the list to the active tenant (or otherwise clearly shows its tenant-scoped by default).
### Tests for User Story 2
- [X] T021 [P] [US2] Add non-mutation test in tests/Feature/Spec085/CanonicalMonitoringDoesNotMutateTenantContextTest.php (GET /admin/operations does not set/clear tenant context)
- [X] T022 [P] [US2] Add scope label test in tests/Feature/Spec085/CanonicalMonitoringDoesNotMutateTenantContextTest.php (no tenant context → "Scope: Workspace — all tenants")
- [X] T023 [P] [US2] Add default-tenant-filter test in tests/Feature/Monitoring/OperationsTenantScopeTest.php (tenant context active → list defaults to active tenant)
### Implementation for User Story 2
- [X] T024 [US2] Ensure Operations index query applies workspace scoping and (when tenant context is active + entitled) tenant scoping without mutating tenant context in app/Filament/Pages/Monitoring/Operations.php
- [X] T025 [US2] Ensure any default tenant filter is applied as a query/filter default only (no calls to Filament::setTenant() during GET) in app/Filament/Pages/Monitoring/Operations.php
**Checkpoint**: US2 meets FR-085-003/004/009.
---
## Phase 5: User Story 3 — Deep links are safe and recoverable (Priority: P3)
**Goal**: On `/admin/operations/{run}`, tenant-context users get a deterministic “Back to <tenant>” plus a secondary “Show all operations”; otherwise only “Back to Operations”.
**Independent Test**: With tenant context active + entitled, GET `/admin/operations/{run}` shows `← Back to <tenant>` and `Show all operations`; without tenant context it shows `Back to Operations` only.
### Tests for User Story 3
- [X] T026 [P] [US3] Add run detail header-action tests in tests/Feature/Spec085/RunDetailBackAffordanceTest.php (tenant context vs no context)
- [X] T027 [P] [US3] Add stale-tenant-context run detail test in tests/Feature/Spec085/RunDetailBackAffordanceTest.php (tenant context set but not entitled → no tenant name, no back-to-tenant)
### Implementation for User Story 3
- [X] T028 [US3] Implement deterministic back affordances for run detail in app/Filament/Pages/Operations/TenantlessOperationRunViewer.php (tenant-context+entitled → “← Back to <tenant>” + “Show all operations”; else “Back to Operations”)
- [X] T029 [US3] Ensure run detail never reveals tenant identity when the viewer is not entitled (stale tenant context treated as workspace-wide) in app/Filament/Pages/Operations/TenantlessOperationRunViewer.php
**Checkpoint**: US3 meets FR-085-006/008/010.
---
## Phase 6: Polish & Cross-Cutting Concerns
- [X] T030 [P] Confirm Spec 085 UI Action Matrix matches implemented header actions in specs/085-tenant-operate-hub/spec.md
- [X] T031 [P] Validate manual verification steps in specs/085-tenant-operate-hub/quickstart.md against actual behavior (update doc only if it drifted)
- [X] T037 Ensure “Show all tenants” clears Operations table tenant filter state (prevents stale Livewire table filter state from keeping the list scoped)
- [X] T032 Run formatting on changed files under app/ and tests/ using vendor/bin/sail bin pint --dirty
- [X] T033 Run focused test suite: vendor/bin/sail artisan test --compact tests/Feature/Spec085 tests/Feature/Monitoring/OperationsTenantScopeTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php
- [X] T034 Fix Filament auth-pattern guard compliance by removing Gate:: usage in app/Filament/Pages/Operations/TenantlessOperationRunViewer.php (use $this->authorize(...))
- [X] T035 Ensure canonical Operate Hub routes sanitize stale/non-entitled tenant context by applying ensure-filament-tenant-selected middleware to /admin/operations, /admin/alerts, /admin/audit-log, and /admin/operations/{run}
- [X] T036 Harden Spec 085-related tests to match final copy/semantics and avoid brittle Livewire DOM assertions (tests/Feature/OpsUx/OperateHubShellTest.php, tests/Feature/Monitoring/OperationsCanonicalUrlsTest.php)
---
## Dependencies & Execution Order
### Dependency Graph
```mermaid
graph TD
P1[Phase 1: Setup] --> P2[Phase 2: Foundational]
P2 --> US1[US1 (P1): Context-aware Monitoring entry]
US1 --> US2[US2 (P2): Canonical URLs + explicit scope]
US1 --> US3[US3 (P3): Deep-link back affordances]
US2 --> P6[Phase 6: Polish]
US3 --> P6
```
### User Story Dependencies
- US1 is the MVP.
- US2 and US3 depend on the shared foundational semantics (scope labels + entitled active tenant resolution).
---
## Parallel Execution Examples
### US1
```text
In parallel:
- T011 (tests) in tests/Feature/Spec085/OperationsIndexHeaderTest.php
- T017 (tenant nav shortcuts) in app/Providers/Filament/TenantPanelProvider.php
Then:
- T018T020 in app/Filament/Pages/Monitoring/Operations.php
```
### US2
```text
In parallel:
- T021T022 (non-mutation + scope label tests)
- T023 (default tenant filter test) in tests/Feature/Monitoring/OperationsTenantScopeTest.php
Then:
- T024T025 in app/Filament/Pages/Monitoring/Operations.php
```
### US3
```text
In parallel:
- T026T027 (run detail tests) in tests/Feature/Spec085/RunDetailBackAffordanceTest.php
Then:
- T028T029 in app/Filament/Pages/Operations/TenantlessOperationRunViewer.php
```
---
## Implementation Strategy
### MVP Scope
- Implement US1 only (T011T020), run T033, then manually validate via specs/085-tenant-operate-hub/quickstart.md.
### Incremental Delivery
- US1 → US2 → US3, keeping each story independently testable.