TenantAtlas/specs/089-provider-connections-tenantless-ui/research.md
2026-02-12 17:32:08 +01:00

3.6 KiB
Raw Blame History

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 → doesnt scale.

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.