Implements Spec 081 provider-connection cutover. Highlights: - Adds provider connection resolution + gating for operations/verification. - Adds provider credential observer wiring. - Updates Filament tenant verify flow to block with next-steps when provider connection isn’t ready. - Adds spec docs under specs/081-provider-connection-cutover/ and extensive Spec081 test coverage. Tests: - vendor/bin/sail artisan test --compact tests/Feature/Filament/TenantSetupTest.php - Focused suites for ProviderConnections/Verification ran during implementation (see local logs). Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Reviewed-on: #98
6.9 KiB
Implementation Plan: Provider Connection Full Cutover
Branch: 081-provider-connection-cutover | Date: 2026-02-07 | Spec: specs/081-provider-connection-cutover/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 viaProviderGateway. - Missing/invalid configuration blocks provider-backed starts but still creates an
OperationRunwith stablereason_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
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
OperationRunOutcomegainsblocked, update badge domain + tests)
Project Structure
Documentation (this feature)
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)
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
- 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
- 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
OperationRunOutcomevalue 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()andtenants.app_*in provider-facing services/jobs. - Resolution rules: default
ProviderConnectionlookup 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 remainscompleted), 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.