TenantAtlas/specs/081-provider-connection-cutover/plan.md
ahmido 4db8030f2a Spec 081: Provider connection cutover (#98)
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
2026-02-08 11:28:51 +00:00

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

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)

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)

Phase 1 — Design & Contracts (complete)

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.