Implements Spec 089: moves Provider Connections to canonical tenantless route under `/admin/provider-connections`, enforces 404/403 semantics (workspace/tenant membership vs capability), adds tenant transparency (tenant column + filter + deep links), adds legacy redirects for old tenant-scoped URLs without leaking Location for 404 cases, and adds regression test coverage (RBAC semantics, filters, UI enforcement tooltips, Microsoft-only MVP scope, navigation placement). Notes: - Filament v5 / Livewire v4 compatible. - Global search remains disabled for Provider Connections. - Destructive/manage actions require confirmation and are policy-gated. Tests: - `vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections` Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #107
162 lines
12 KiB
Markdown
162 lines
12 KiB
Markdown
# Tasks: Provider Connections (Tenantless UI + Tenant Transparency)
|
||
|
||
**Input**: Design documents from `specs/089-provider-connections-tenantless-ui/`
|
||
**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/
|
||
|
||
**Tests**: Required (Pest) — this feature changes runtime auth + routing.
|
||
|
||
---
|
||
|
||
## Phase 1: Setup (Shared Infrastructure)
|
||
|
||
- [X] T001 Confirm spec artifacts present in specs/089-provider-connections-tenantless-ui/{spec,plan,research,data-model,quickstart,tasks}.md
|
||
- [X] T002 [P] Validate existing provider capabilities exist in app/Support/Auth/Capabilities.php (PROVIDER_VIEW/PROVIDER_MANAGE/PROVIDER_RUN)
|
||
- [X] T003 [P] Inventory existing Provider Connections routes/actions and update the UI Action Matrix in specs/089-provider-connections-tenantless-ui/spec.md (anchor to app/Filament/Resources/ProviderConnectionResource.php)
|
||
|
||
---
|
||
|
||
## Phase 2: Foundational (Blocking Prerequisites)
|
||
|
||
- [X] T004 Define tenant-context default filter precedence contract for Provider Connections (query `tenant_id` overrides session TenantContext) in app/Filament/Resources/ProviderConnectionResource.php
|
||
- [X] T005 Implement JOIN-based tenant-membership scoping query helper for Provider Connections in app/Filament/Resources/ProviderConnectionResource.php (no large in-memory tenant-id lists)
|
||
- [X] T006 Ensure non-workspace member access is deny-as-not-found (404) for Provider Connections surfaces via existing middleware/policy wiring (verify and adjust in app/Policies/ProviderConnectionPolicy.php and panel middleware if needed)
|
||
- [X] T007 Create baseline authorization regression tests for 404 vs 403 semantics in tests/Feature/ProviderConnections/AuthorizationSemanticsTest.php
|
||
|
||
**Checkpoint**: Foundation ready (tenant resolution, scoping approach, baseline auth tests).
|
||
|
||
---
|
||
|
||
## Phase 3: User Story 1 — Workspace-weite Übersicht (Priority: P1) 🎯 MVP
|
||
|
||
**Goal**: Canonical tenantless route + central navigation placement + tenant transparency on list with safe scoping and default filtering.
|
||
|
||
**Independent Test**: Workspace member sees only entitled tenant rows at `/admin/provider-connections`, default filter respects TenantContext, `?tenant_id=` overrides, non-workspace member gets 404.
|
||
|
||
### Tests (write first)
|
||
|
||
- [X] T008 [P] [US1] Add feature test for canonical list route 404 for non-workspace member in tests/Feature/ProviderConnections/TenantlessListRouteTest.php
|
||
- [X] T009 [P] [US1] Add feature test for scoping: member of Tenant A not Tenant B sees only A rows in tests/Feature/ProviderConnections/TenantlessListScopingTest.php
|
||
- [X] T010 [P] [US1] Add feature test for `tenant_id` query override (authorized tenant shows rows; unauthorized tenant shows 0 rows) in tests/Feature/ProviderConnections/TenantFilterOverrideTest.php
|
||
|
||
### Implementation
|
||
|
||
- [X] T011 [US1] Change canonical Filament resource slug to tenantless in app/Filament/Resources/ProviderConnectionResource.php (from `tenants/{tenant}/provider-connections` to `provider-connections`)
|
||
- [X] T012 [US1] Update Provider Connections navigation placement in app/Filament/Resources/ProviderConnectionResource.php (group: `Settings`, subgroup: `Integrations`, label: `Provider Connections`)
|
||
- [X] T013 [US1] Update ProviderConnectionResource::getUrl behavior in app/Filament/Resources/ProviderConnectionResource.php to stop inferring `{tenant}` path params and instead support tenant filter via query string
|
||
- [X] T014 [US1] Update ProviderConnectionResource::getEloquentQuery() in app/Filament/Resources/ProviderConnectionResource.php to allow tenantless list + record access while enforcing workspace + tenant membership scoping at query time
|
||
- [X] T015 [US1] Update list query scoping in app/Filament/Resources/ProviderConnectionResource.php to: workspace-scope + membership join + optional tenant filter (`tenant_id` query > TenantContext default)
|
||
- [X] T016 [US1] Add required tenant transparency columns + filters in app/Filament/Resources/ProviderConnectionResource.php (Tenant column with deep link to Tenant view + Tenant filter)
|
||
- [X] T017 [US1] Add required list columns for last error reason/message in app/Filament/Resources/ProviderConnectionResource.php (reason code + truncated message, sanitized)
|
||
- [X] T018 [US1] Ensure list has a clear inspection affordance and action-surface contract compliance in app/Filament/Resources/ProviderConnectionResource.php (prefer `recordUrl()` clickable rows; keep max 2 visible row actions)
|
||
- [X] T019 [US1] Add meaningful empty state + CTA behavior to app/Filament/Resources/ProviderConnectionResource/Pages/ListProviderConnections.php
|
||
|
||
### Legacy redirect
|
||
|
||
- [X] T020 [US1] Add legacy redirects for workspace-managed tenant routes in routes/web.php (302 only for entitled members; otherwise 404; no Location leaks): `/admin/tenants/{tenant:external_id}/provider-connections` → `/admin/provider-connections?tenant_id={tenant_external_id}`, `/admin/tenants/{tenant:external_id}/provider-connections/create` → `/admin/provider-connections/create?tenant_id={tenant_external_id}`, `/admin/tenants/{tenant:external_id}/provider-connections/{record}/edit` → `/admin/provider-connections/{record}/edit?tenant_id={tenant_external_id}`
|
||
- [X] T021 [P] [US1] Add legacy redirect tests in tests/Feature/ProviderConnections/LegacyRedirectTest.php (302 for entitled; 404 for non-workspace/non-tenant members; assert no Location header for 404 cases; assert `/admin/t/{tenant_external_id}/provider-connections` remains 404 and does not redirect)
|
||
|
||
**Checkpoint**: US1 delivers canonical tenantless list + safe scoping + redirect.
|
||
|
||
---
|
||
|
||
## Phase 4: User Story 2 — Sicherer Detail-/Edit-Zugriff ohne Secrets (Priority: P2)
|
||
|
||
**Goal**: Secure view/edit + actions gated by capability; non-member 404; member missing capability 403; no plaintext secrets.
|
||
|
||
**Independent Test**: Direct record access behaves as spec (404/403), manage actions are confirmed + audited, run actions create OperationRun, secrets never displayed.
|
||
|
||
### Tests (write first)
|
||
|
||
- [X] T022 [P] [US2] Add feature test: non-tenant member direct record access is 404 in tests/Feature/ProviderConnections/RecordAccessNotFoundTest.php
|
||
- [X] T023 [P] [US2] Add feature test: tenant member missing Capabilities::PROVIDER_VIEW gets 403 for list/detail in tests/Feature/ProviderConnections/CapabilityForbiddenTest.php (no raw capability strings)
|
||
- [X] T024 [P] [US2] Add feature test: tenant member missing Capabilities::PROVIDER_MANAGE cannot mutate (403) in tests/Feature/ProviderConnections/ManageCapabilityEnforcementTest.php (no raw capability strings)
|
||
|
||
### Implementation
|
||
|
||
- [X] T025 [US2] Add a Provider Connection View page (required for “detail” semantics) in app/Filament/Resources/ProviderConnectionResource/Pages/ViewProviderConnection.php and register it in app/Filament/Resources/ProviderConnectionResource.php getPages()
|
||
- [X] T026 [US2] Update record routes to tenantless paths in app/Filament/Resources/ProviderConnectionResource.php and related Pages/* so record URLs no longer depend on `{tenant}`
|
||
- [X] T027 [US2] Update authorization semantics (404 for non-members; 403 for missing capability; viewAny/view=Capabilities::PROVIDER_VIEW; create/update/delete=Capabilities::PROVIDER_MANAGE) in app/Policies/ProviderConnectionPolicy.php
|
||
- [X] T028 [US2] Update Edit page tenant resolution to prefer record’s tenant (not route tenant) in app/Filament/Resources/ProviderConnectionResource/Pages/EditProviderConnection.php
|
||
- [X] T029 [US2] Update Create page to require explicit tenant selection (query `tenant_id` or context default) in app/Filament/Resources/ProviderConnectionResource/Pages/CreateProviderConnection.php (abort 404 if no entitled tenant can be resolved)
|
||
- [X] T030 [US2] Ensure all destructive-like/manage actions require confirmation in app/Filament/Resources/ProviderConnectionResource.php and app/Filament/Resources/ProviderConnectionResource/Pages/EditProviderConnection.php (enable/disable, set default, credential updates)
|
||
- [X] T031 [US2] Ensure manage actions write AuditLog using the correct logger (tenant/workspace as appropriate) and do not include secrets in context (review and adjust in app/Filament/Resources/ProviderConnectionResource.php and Pages/EditProviderConnection.php)
|
||
- [X] T032 [US2] Ensure run/health actions create/reuse OperationRun and link to canonical viewer (verify OperationRunLinks tenantless path usage in app/Filament/Resources/ProviderConnectionResource.php and Pages/EditProviderConnection.php)
|
||
- [X] T033 [US2] Ensure UI never renders plaintext secrets and provides no secret copy affordances (confirm forms/columns in app/Filament/Resources/ProviderConnectionResource.php)
|
||
|
||
**Checkpoint**: US2 secures detail/edit surfaces + action gating + confirmations.
|
||
|
||
---
|
||
|
||
## Phase 5: User Story 3 — Tenant-Detailseite zeigt effektiven Provider-State + Deep Link (Priority: P3)
|
||
|
||
**Goal**: Tenant view shows effective default provider connection state and links to tenant-filtered canonical list.
|
||
|
||
**Independent Test**: Tenant view displays default connection summary and CTA to `/admin/provider-connections?tenant_id=<tenant>`.
|
||
|
||
### Tests (write first)
|
||
|
||
- [X] T034 [P] [US3] Add feature test asserting tenant view contains CTA URL to canonical provider connections with tenant_id in tests/Feature/Tenants/TenantProviderConnectionsCtaTest.php
|
||
|
||
### Implementation
|
||
|
||
- [X] T035 [US3] Update tenant header action URL to tenantless canonical list in app/Filament/Resources/TenantResource/Pages/ViewTenant.php (use `/admin/provider-connections?tenant_id={external_id}` semantics)
|
||
- [X] T036 [US3] Add “Provider connection” effective state section to the tenant infolist in app/Filament/Resources/TenantResource.php (display name, status/health, last check; show needs-action state if missing)
|
||
- [X] T037 [US3] Add a dedicated infolist entry view for the provider connection state in resources/views/filament/infolists/entries/provider-connection-state.blade.php
|
||
|
||
**Checkpoint**: US3 completes tenant transparency from tenant detail.
|
||
|
||
---
|
||
|
||
## Phase 6: Polish & Cross-Cutting Concerns
|
||
|
||
- [X] T038 [P] Run targeted test suite for Provider Connections changes: `vendor/bin/sail artisan test --compact tests/Feature/ProviderConnections` (add notes to specs/089-provider-connections-tenantless-ui/quickstart.md if paths differ)
|
||
- [X] T039 [P] Run formatting and fix any findings in app/** and tests/** using `vendor/bin/sail bin pint --dirty`
|
||
- [X] T040 Review navigation grouping consistency for Settings → Integrations in app/Providers/Filament/AdminPanelProvider.php (ensure Provider Connections appears where spec requires)
|
||
- [X] T041 Validate that Provider Connections remains excluded from global search in app/Filament/Resources/ProviderConnectionResource.php
|
||
|
||
- [X] T042 [P] Add regression test asserting disabled actions render with helper text/tooltip for tenant members missing capability (UI enforcement) in tests/Feature/ProviderConnections/DisabledActionsTooltipTest.php (or add an explicit exemption in specs/089-provider-connections-tenantless-ui/spec.md if not feasible)
|
||
- [X] T043 [P] Add regression test asserting required list filters exist and behave (Provider, Status, Health, Default-only) in tests/Feature/ProviderConnections/RequiredFiltersTest.php
|
||
- [X] T044 [P] Add regression test asserting MVP provider scope remains Microsoft-only (no non-Microsoft provider options exposed) in tests/Feature/ProviderConnections/MvpProviderScopeTest.php
|
||
|
||
---
|
||
|
||
## Dependencies & Execution Order
|
||
|
||
- Setup (T001–T003) → Foundational (T004–T007) → US1 (T008–T021) → US2 (T022–T033) → US3 (T034–T037) → Polish (T038–T044)
|
||
|
||
```mermaid
|
||
graph TD
|
||
P1[Phase 1: Setup] --> P2[Phase 2: Foundational]
|
||
P2 --> US1[US1: Tenantless List]
|
||
P2 --> US2[US2: Secure View/Edit]
|
||
P2 --> US3[US3: Tenant View State]
|
||
US1 --> Polish[Phase 6: Polish]
|
||
US2 --> Polish
|
||
US3 --> Polish
|
||
```
|
||
|
||
## Parallel Execution Examples
|
||
|
||
### US1
|
||
|
||
- Run in parallel:
|
||
- T008, T009, T010 (tests)
|
||
- T020 + T021 (redirect + test) can be done alongside T011–T019 once slug decision is finalized
|
||
|
||
### US2
|
||
|
||
- Run in parallel:
|
||
- T022–T024 (tests)
|
||
- T025 (View page scaffolding) and T027 (policy fixes) can be developed independently
|
||
|
||
### US3
|
||
|
||
- Run in parallel:
|
||
- T034 (test) and T037 (Blade entry view) while T036 changes TenantResource infolist
|
||
|
||
## Implementation Strategy
|
||
|
||
- MVP = US1 only (canonical tenantless list + safe scoping + legacy redirect).
|
||
- Add US2 next (secure detail/edit + action confirmations + audit/run correctness).
|
||
- Add US3 last (tenant view effective-state + CTA).
|