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
83 lines
3.6 KiB
Markdown
83 lines
3.6 KiB
Markdown
# Phase 0 Research — Provider Connections (Tenantless UI)
|
||
|
||
**Branch**: `089-provider-connections-tenantless-ui`
|
||
**Date**: 2026-02-12
|
||
|
||
This document resolves planning unknowns and records decisions with rationale.
|
||
|
||
## Findings (Repo Reality)
|
||
|
||
- Provider connections already exist as a Filament resource with a tenant-scoped slug.
|
||
- The app has a concept of an active workspace context (session-selected) and an active tenant context.
|
||
- Workspace membership and tenant membership are treated as hard isolation boundaries (deny-as-not-found 404).
|
||
- There are existing patterns for:
|
||
- Query scoping by workspace + tenant membership
|
||
- UI enforcement (disabled actions + tooltips) with server-side 403 enforcement
|
||
- Audit logging (AuditLog) for state changes
|
||
- OperationRun for observable run/health operations
|
||
- Legacy redirect precedent (tenant-scoped → tenantless) for Operations
|
||
|
||
## Decisions
|
||
|
||
### D1 — Canonical routing (tenantless)
|
||
|
||
**Decision**: Provider Connections will move to a canonical tenantless admin route: `/admin/provider-connections`.
|
||
|
||
**Rationale**: Removes fragile tenant-route coupling, matches enterprise IA, and simplifies testing.
|
||
|
||
**Alternatives considered**:
|
||
- Keep tenant-scoped slug and add more navigation shortcuts.
|
||
- Create a separate “workspace integrations” page and keep resource tenant-scoped.
|
||
|
||
### D2 — MVP provider scope
|
||
|
||
**Decision**: MVP supports Microsoft (Graph) as the only provider; UI/IA remains generic “Provider Connections”.
|
||
|
||
**Rationale**: Reduces scope while keeping the data model/provider column future-proof.
|
||
|
||
**Alternatives considered**:
|
||
- Rename IA to “Microsoft Graph Connections” (more precise but less extensible).
|
||
- Support multiple providers in MVP (expensive and not required for current goal).
|
||
|
||
### D3 — Tenant context default filtering
|
||
|
||
**Decision**: Default tenant filter resolves from active TenantContext (session/context switcher). If `tenant_id` is present in the query string, it takes precedence.
|
||
|
||
**Rationale**: Matches existing tenant-context behavior across tenantless pages while enabling deep links (e.g., from tenant detail) without special referrer logic.
|
||
|
||
**Alternatives considered**:
|
||
- Only querystring (no session context) → worse UX and inconsistent with app patterns.
|
||
- Persist per-page last filter only → adds state complexity and surprise.
|
||
|
||
### D4 — Zero-leak scoping strategy (JOIN-based)
|
||
|
||
**Decision**: ProviderConnections list/query will be scoped using query-time membership joins (workspace + tenant), not large in-memory ID lists.
|
||
|
||
**Rationale**: Supports MSP scale and avoids `whereIn([ids])` lists.
|
||
|
||
**Alternatives considered**:
|
||
- Load entitled tenant IDs in PHP and apply `whereIn` → doesn’t scale.
|
||
|
||
### D5 — Global search
|
||
|
||
**Decision**: Provider Connections will not appear in Global Search.
|
||
|
||
**Rationale**: Global search is a high-leak vector for cross-tenant metadata previews; navigation placement makes search unnecessary.
|
||
|
||
**Alternatives considered**:
|
||
- Enable global search with strict scoping → still increases risk surface and complexity.
|
||
|
||
### D6 — Auditability
|
||
|
||
**Decision**: Manage/state-change actions write an AuditLog entry. Run/health actions create an OperationRun with canonical “view run” link.
|
||
|
||
**Rationale**: Aligns with constitution: state changes are auditable and operations are observable.
|
||
|
||
**Alternatives considered**:
|
||
- Only AuditLog → loses operational traceability for runs.
|
||
- Only OperationRun → weaker governance for state change events.
|
||
|
||
## Open Questions
|
||
|
||
None remaining for planning. Implementation will confirm exact join table names and reuse existing scoping helpers.
|