## Summary - introduce the Provider Connection Filament resource (list/create/edit) with DB-only controls, grouped action dropdowns, and badge-driven status/health rendering - wire up the provider foundation stack (migrations, models, policies, providers, operations, badges, and audits) plus the required spec docs/checklists - standardize Inventory Sync notifications so the job no longer writes its own DB rows; terminal notifications now flow exclusively through OperationRunCompleted while the start surface still shows the queued toast ## Testing - ./vendor/bin/sail php ./vendor/bin/pint --dirty - ./vendor/bin/sail artisan test tests/Unit/Badges/ProviderConnectionBadgesTest.php - ./vendor/bin/sail artisan test tests/Feature/ProviderConnections tests/Feature/Filament/ProviderConnectionsDbOnlyTest.php - ./vendor/bin/sail artisan test tests/Feature/Inventory/RunInventorySyncJobTest.php tests/Feature/Inventory/InventorySyncStartSurfaceTest.php Co-authored-by: Ahmed Darrazi <ahmeddarrazi@MacBookPro.fritz.box> Reviewed-on: #73
131 lines
8.9 KiB
Markdown
131 lines
8.9 KiB
Markdown
# Implementation Plan: Provider Foundation v1 (Microsoft-first, Security-first)
|
|
|
|
**Branch**: `061-provider-foundation` | **Date**: 2026-01-24 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/spec.md`
|
|
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/spec.md`
|
|
|
|
**Note**: This template is filled in by the `/speckit.plan` command. See `.specify/scripts/` for helper scripts.
|
|
|
|
## Summary
|
|
|
|
- Introduce tenant-scoped Microsoft provider connections (multiple allowed) with a required default connection and isolated credentials.
|
|
- Centralize all Microsoft Graph access through the existing Graph contract path (`GraphClientInterface` + `config/graph_contracts.php`) while standardizing provider operation context and failure handling.
|
|
- Add provider capability interfaces (health check, inventory, compliance, placeholders) so future provider modules can be introduced without scattering provider-specific logic.
|
|
- Run all provider operations asynchronously as canonical `OperationRun`s with clear UX rules: same-operation dedupe returns the active run; different-operation requests are blocked as “scope busy” with a link to the active run.
|
|
- Guarantee DB-only render for Provider Connections and Monitoring surfaces; outbound calls occur only in queued jobs.
|
|
- Add regression tests for tenant isolation, role authorization, dedupe/scope-busy behavior, and secret redaction in run failures.
|
|
|
|
## 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 (Laravel 12)
|
|
**Primary Dependencies**: Laravel 12 + Filament v5 + Livewire v4
|
|
**Storage**: PostgreSQL (Sail) with JSONB where appropriate
|
|
**Testing**: Pest (PHPUnit)
|
|
**Target Platform**: Web application (Sail/Docker locally; container deploy via Dokploy)
|
|
**Project Type**: web
|
|
**Performance Goals**: DB-only pages render fast (no outbound calls); operation start surfaces respond quickly after enqueueing a run
|
|
**Constraints**: No outbound HTTP during render/poll/hydration; max 1 active provider run per Entra tenant scope; secrets/tokens never persisted in runs/logs. Remote provider calls are read-only (Graph fetches), but the platform will persist local state (snapshots/summary_counts/health) as DB writes.
|
|
**Scale/Scope**: Multiple suite tenants; multiple Microsoft connections per tenant; operations history grows over time (indexing required)
|
|
|
|
## Constitution Check
|
|
|
|
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
|
|
|
- Inventory-first, snapshots-second: PASS (provider inventory is treated as “last observed”; no backup/restore semantics introduced in v1).
|
|
- Read/write separation: PASS (v1 provider operations perform remote reads only, while persisting local DB state such as health and snapshot summaries. Any future remote writes (e.g., script deploy/app publish) remain out of scope and would require preview + confirmation + audit + tests).
|
|
- Single contract path to Graph: PASS (all Microsoft Graph calls stay behind `GraphClientInterface` and are modeled in `config/graph_contracts.php`; no ad-hoc HTTP in UI/render).
|
|
- Deterministic capabilities: PASS (provider operations are registered centrally and validated/tested; no “quick endpoints” scattered across features).
|
|
- Tenant isolation: PASS (provider connections, credentials, and runs are scoped to the current Suite Tenant; cross-tenant access is denied-as-not-found).
|
|
- Operations / run observability standard: PASS (all provider operations create/reuse a canonical `OperationRun`; start surfaces enqueue-only; Monitoring remains DB-only).
|
|
- Automation (locks + idempotency): PASS (same-operation starts dedupe to the active run; different-operation starts for the same scope are blocked as “scope busy”; Graph throttling handled via existing retry/backoff+jitter).
|
|
- Data minimization & safe logging: PASS (no secrets/tokens persisted or logged; failures use stable reason codes + sanitized short messages).
|
|
- Badge semantics (BADGE-001): PASS (any status-like UI badges for connection status/health must render via `BadgeCatalog` / `BadgeRenderer` with tests; otherwise status is shown as plain text).
|
|
|
|
## Project Structure
|
|
|
|
### Documentation (this feature)
|
|
|
|
```text
|
|
specs/061-provider-foundation/
|
|
├── 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)
|
|
|
|
```text
|
|
app/
|
|
├── Filament/
|
|
├── Jobs/
|
|
├── Models/
|
|
├── Policies/
|
|
├── Services/
|
|
│ ├── Graph/
|
|
│ └── Operations/
|
|
└── Support/
|
|
|
|
config/
|
|
database/
|
|
resources/
|
|
routes/
|
|
tests/
|
|
```
|
|
|
|
**Structure Decision**: Single Laravel web application with Filament admin panel; provider foundation lives in `app/Models`, `app/Services`, `app/Jobs`, `app/Policies`, and integrates with the existing Graph + Operations infrastructure.
|
|
|
|
## Complexity Tracking
|
|
|
|
No constitution violations required for this feature.
|
|
|
|
## Phase 0 — Research (output: `research.md`)
|
|
|
|
See: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/research.md`
|
|
|
|
Goals:
|
|
- Confirm the existing Graph contract path and reuse it (no new bespoke HTTP client in UI/features).
|
|
- Confirm token acquisition is app-only (client credentials) and is sourced from `provider_credentials` via `CredentialManager` inside `ProviderGateway` (no secrets in config/env beyond bootstrap).
|
|
- Ensure provider operations supply auth context to `GraphClientInterface` via `ProviderGateway` (the only decryptor), not from UI/service layers.
|
|
- Confirm `GraphClientInterface` binding can be enabled without env secrets when `ProviderGateway` supplies per-request credentials (e.g., via a `GRAPH_ENABLED` override).
|
|
- Confirm existing `OperationRun` idempotency patterns and align provider operations with them.
|
|
- Confirm existing sanitization / reason-code utilities for run failures and reuse them.
|
|
|
|
## Phase 1 — Design & Contracts (outputs: `data-model.md`, `contracts/`, `quickstart.md`)
|
|
|
|
See:
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/data-model.md`
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/contracts/`
|
|
- `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/061-provider-foundation/quickstart.md`
|
|
|
|
Design focus:
|
|
- Data model for provider connections + isolated credentials with a required default connection.
|
|
- Credential isolation: `provider_credentials` stores encrypted payload; only ProviderGateway/CredentialManager can decrypt; never expose in resources/logs/runs.
|
|
- Provider module contracts: define capability interfaces and ensure Microsoft implementations depend on `ProviderGateway` rather than calling Graph directly.
|
|
- OperationRun identity + scope-busy behavior consistent with clarified UX rules.
|
|
- Explicit Graph contract registry updates required for new provider operations.
|
|
|
|
## Phase 2 — Implementation Outline (tasks created in `/speckit.tasks`)
|
|
|
|
- Schema: create provider connection + credential tables, indexes, and state fields.
|
|
- Authorization (capabilities-first): implement gates/policies `provider.view`, `provider.manage`, `provider.run`.
|
|
- Owner/Manager: view+manage+run; Operator: view+run; Readonly: view only.
|
|
- No `role == X` checks in feature code; enforce via policies/gates + tests.
|
|
- Provider foundation services: connection resolution (default/explicit), credential resolution, and operation registry.
|
|
- Provider gateway + modules: implement `ProviderGateway`, `CredentialManager`, and capability interfaces used by all provider operations.
|
|
- Operations: implement health check, inventory collection (minimal), and compliance snapshot (counts) as queued `OperationRun`s.
|
|
- Concurrency: same-operation dedupe to active run; different-operation blocked as “scope busy” with active-run link; enforce race-safety with a DB lock/transaction around start-gate decisions.
|
|
- UI: Provider Connections management is DB-only at render; “Check connection” and any provider operations are enqueue-only (jobs perform outbound HTTP). Add a DB-only render test with Http::fake() asserting zero outbound requests during render/poll/hydration.
|
|
- Guardrails/tests: DB-only render tests, secret-redaction tests, reason-code mapping tests, concurrency behavior tests.
|
|
|
|
## Constitution Check (Post-Design)
|
|
|
|
Re-check result: PASS. Design artifacts explicitly keep Graph calls behind `GraphClientInterface` + contract registry and standardize provider operations via `OperationRun` with tenant isolation, idempotency, and safe failure handling.
|