# Implementation Plan: Provider Connection Full Cutover

**Branch**: `081-provider-connection-cutover` | **Date**: 2026-02-07 | **Spec**: [specs/081-provider-connection-cutover/spec.md](spec.md)
**Input**: Feature specification from `specs/081-provider-connection-cutover/spec.md`

**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.

## Summary

Cut over all provider-facing runtime flows from legacy tenant-stored app credentials (`tenants.app_*`) to a single, deterministic credential source: `ProviderConnection` + `ProviderCredential`.

Key behaviors:

- Runtime provider calls resolve a `ProviderConnection` (default per tenant/provider) and build Graph options via `ProviderGateway`.
- Missing/invalid configuration blocks provider-backed starts but still creates an `OperationRun` with stable `reason_code` + link-only next steps.
- A one-time, idempotent backfill ensures Microsoft default connections exist/are repaired using the decision tree in the spec.

## Technical Context

<!--
  ACTION REQUIRED: Replace the content in this section with the technical details
  for the project. The structure here is presented in advisory capacity to guide
  the iteration process.
-->

**Language/Version**: PHP 8.4.15  
**Primary Dependencies**: Laravel 12, Filament v5, Livewire v4, Socialite v5  
**Storage**: PostgreSQL (via Laravel Sail)  
**Testing**: Pest v4 + PHPUnit v12 (run via `vendor/bin/sail artisan test --compact`)  
**Target Platform**: Laravel web application (Sail-first local dev; Dokploy container deploy)  
**Project Type**: Web application (Filament admin + queued jobs)  
**Performance Goals**: Deterministic provider operations; no remote calls during page render; avoid N+1 patterns in tables/global search  
**Constraints**: Secrets must never appear in logs/audits/reports; Graph calls only via `GraphClientInterface` and contract registry; blocked starts must still create observable runs  
**Scale/Scope**: Enterprise multi-tenant workspace; provider operations are queued and deduped via `OperationRun`

## Constitution Check

*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

- Inventory-first: PASS (no changes to inventory/snapshot semantics; cutover affects provider auth only)
- Read/write separation: PASS (credential mutations remain confirmed + audited; provider operations remain `OperationRun`-tracked)
- Graph contract path: PASS (provider calls continue via `GraphClientInterface`; no new Graph endpoints introduced by this spec)
- Deterministic capabilities: PASS (no capability derivation changes required; enforce central resolver usage where needed)
- RBAC-UX planes + 404/403 semantics: PASS (provider connection management remains tenant-scoped; non-members 404, members missing capability 403)
- Destructive confirmation standard: PASS (credential rotation/mutations require confirmation; enforced server-side)
- Global search tenant safety: PASS (no new global search surfaces introduced in this spec)
- Tenant isolation: PASS (provider connections are workspace-owned + tenant-scoped; no cross-tenant shortcuts)
- Run observability: PASS (blocked starts still create runs; Monitoring remains DB-only)
- Automation: PASS (jobs remain queued + idempotent; throttling/backoff policies unchanged)
- Data minimization & safe logging: PASS (explicitly prohibit secrets in logs/audits/reports)
- Badge semantics (BADGE-001): PASS WITH WORK (if `OperationRunOutcome` gains `blocked`, update badge domain + tests)

## Project Structure

### Documentation (this feature)

```text
specs/081-provider-connection-cutover/
├── plan.md              # This file (/speckit.plan command output)
├── research.md          # Phase 0 output (/speckit.plan command)
├── data-model.md        # Phase 1 output (/speckit.plan command)
├── quickstart.md        # Phase 1 output (/speckit.plan command)
├── contracts/           # Phase 1 output (/speckit.plan command)
└── tasks.md             # Phase 2 output (/speckit.tasks command - NOT created by /speckit.plan)
```

### Source Code (repository root)
<!--
  ACTION REQUIRED: Replace the placeholder tree below with the concrete layout
  for this feature. Delete unused options and expand the chosen structure with
  real paths (e.g., apps/admin, packages/something). The delivered plan must
  not include Option labels.
-->

```text
app/
├── Console/Commands/
├── Filament/
│   ├── Pages/
│   └── Resources/
├── Jobs/
├── Models/
├── Policies/
├── Services/
│   ├── Graph/
│   ├── Intune/
│   ├── Inventory/
│   └── Providers/
└── Support/

config/
└── graph_contracts.php

database/
├── factories/
└── migrations/

tests/
├── Feature/
└── Unit/
```

**Structure Decision**: Laravel monolith with Filament admin and queued operations; provider integrations live under `app/Services/Providers/*` with Graph calls routed via `GraphClientInterface` + `config/graph_contracts.php`.

## Complexity Tracking

> **Fill ONLY if Constitution Check has violations that must be justified**

| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| N/A | N/A | N/A |

## Phase 0 — Outline & Research (complete)

- Output: [specs/081-provider-connection-cutover/research.md](research.md)
- Key repo facts captured: existing `ProviderConnection`/`ProviderCredential`, partial unique index for defaults, and identified legacy tenant-credential read hotspots.

## Phase 1 — Design & Contracts (complete)

- Output: [specs/081-provider-connection-cutover/data-model.md](data-model.md)
- Output: `specs/081-provider-connection-cutover/contracts/*`
- Output: `specs/081-provider-connection-cutover/quickstart.md`

### Post-design Constitution Re-check

- PASS: No render-time provider calls are introduced.
- PASS: Provider calls remain behind the Graph contract registry and gateway.
- PASS WITH WORK: Any new `OperationRunOutcome` value requires centralized badge mapping + tests.

## Phase 2 — Implementation Planning (next)

`tasks.md` will be produced by `/speckit.tasks` and should cover, at minimum:

- Runtime cutover: remove/replace all uses of `Tenant::graphOptions()` and `tenants.app_*` in provider-facing services/jobs.
- Resolution rules: default `ProviderConnection` lookup per (tenant, provider), with deterministic error/blocked semantics.
- Backfill command: `tenantpilot:provider-connections:backfill-microsoft-defaults` (idempotent, safe, no duplicates).
- Operations: represent blocked starts as `outcome=blocked` (status remains `completed`), with stable reason codes and link-only next steps.
- Filament UI: remove tenant credential fields and consolidate credential management under provider connections with confirmed actions.
- Regression guards: tests that fail on runtime legacy reads + tests for backfill, blocked runs, and badge mapping.
