# 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.
