# Implementation Plan: Backup/Restore UI Graph-Safety (Phase 1) **Branch**: `feat/048-backup-restore-ui-graph-safety` | **Date**: 2026-01-11 | **Spec**: specs/048-backup-restore-ui-graph-safety/spec.md **Input**: Feature specification from `specs/048-backup-restore-ui-graph-safety/spec.md` ## Summary Ensure Backup/Restore Filament UI is Graph-safe by construction: - No Microsoft Graph calls during render/mount/options/typeahead. - Restore wizard group mapping UI shows DB-only fallback labels (`…`) instead of resolving names via Graph. - Add fail-hard Pest feature tests that bind `GraphClientInterface` to throw and still allow: - Backup Sets index to render (HTTP 200 + stable marker) - Restore wizard to render (HTTP 200 + stable marker) ## Technical Context **Language/Version**: PHP 8.2+ (repo guidance targets PHP 8.4.x) **Primary Dependencies**: Laravel 12, Filament 4, Livewire 3 **Storage**: PostgreSQL (JSON columns used for snapshots/preview/results/mappings) **Testing**: Pest 4 (via `php artisan test`), PHPUnit 12 under the hood **Target Platform**: Sail-first local dev (Docker), Dokploy-first staging/prod (containers) **Project Type**: Laravel monolith (Filament admin UI + jobs/services) **Performance Goals**: N/A (UI correctness + safety) **Constraints**: - UI render must be DB-only (no Graph in request lifecycle) - No new tables/migrations in Phase 1 - Keep surface area minimal and low-risk **Scale/Scope**: Multi-tenant admin app; tests must enforce tenant scoping and guardrails ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - Inventory-first: PASS (this phase only hardens UI render boundaries; no changes to SoT semantics) - Read/write separation: PASS (no restore execution changes; tests cover render only) - Single contract path to Graph: PASS (goal is “no Graph in UI render”; Graph stays behind `GraphClientInterface`) - Deterministic capabilities: PASS (no capability derivation changes) - Tenant isolation: PASS (tests use tenant-scoped URLs and seeded tenant data) - Automation idempotent/observable: PASS (no job/scheduler changes in Phase 1) - Data minimization & safe logging: PASS (no new stored data or logs) ## Project Structure ### Documentation (this feature) ```text specs/048-backup-restore-ui-graph-safety/ ├── plan.md # This file (/speckit.plan output) ├── research.md # Phase 0 output ├── data-model.md # Phase 1 output ├── quickstart.md # Phase 1 output ├── contracts/ # Phase 1 output └── tasks.md # Task breakdown (already present) ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ ├── Resources/ │ │ ├── BackupSetResource.php │ │ └── RestoreRunResource.php │ └── Resources/*/Pages/ ├── Providers/ │ ├── AppServiceProvider.php # GraphClientInterface binding │ └── Filament/AdminPanelProvider.php # panel path + tenant routing ├── Services/ │ └── Graph/ │ ├── GraphClientInterface.php │ └── NullGraphClient.php database/migrations/ tests/Feature/ ``` **Structure Decision**: Laravel monolith (Filament admin UI + services). No new top-level folders. ## Complexity Tracking None.