Summary Dieses PR führt Spec 048: Backup/Restore UI Graph-Safety ein. Ziel: Backup/Restore-Screens in Filament sollen stabil und skalierbar bleiben, indem keine Microsoft Graph Calls beim UI-Rendern (mount/render/options/typeahead/labels) stattfinden. Stattdessen: DB-only Render + klare Fallbacks + Guard-Tests, die jede versehentliche UI-Graph-Nutzung sofort brechen. ⸻ Motivation / Problem Im aktuellen Stand rutschen Graph Calls gerne in: • Restore Wizard Group-Typeahead / getOptionLabelUsing (Graph /groups) • “Preview/Dry-Run” oder Label-Resolution im UI-Request Das führt zu: • langsamen/fragilen Pages (429/Timeout/Permissions) • schwerer Debugbarkeit im MSP-Scale • unerwarteten Abhängigkeiten vom Graph in reinen UI-Views ⸻ Scope (Phase 1, MVP) In scope • UI Render DB-only: Keine Graph Calls in Filament Render-Pfaden (Backup + Restore) • Fallback Labels für unresolved IDs: • Format: Unresolved (…<last8>) • Group Mapping UX (DB-only): • manuelle GUID Eingabe • GUID Validation • Helper-Text, wo Admins die Object ID finden • kein Graph-Search/typeahead • Fail-hard Guard Tests als Pest Feature Tests (HTTP GET): • Render Backup Sets Index • Render Restore Wizard • Tests assert: 200 OK + stable marker string Out of scope • Job-Orchestration Refactor (Actions wie “Capture snapshot”, “Rerun restore”, “dry-run execution”) → separater Spec/Feature • Entra Group Name Resolution (Group Inventory / Cache) → separater Modul-Scope ⸻ Deliverables • spec.md, plan.md, tasks.md • checklists/requirements.md (constitution gate) • Klar definierte Marker-Regeln für Guard-Tests (statische Headings, keine dynamischen Row-Werte) ⸻ Success Criteria • Guard-Tests schlagen zuverlässig fehl, sobald ein UI-Render Pfad Graph aufruft. • Restore Wizard bleibt bedienbar ohne Graph-Typeahead (GUID manual entry + Validation). • Keine DB-Migrations in dieser Phase. ⸻ Next Step Nach Review/Merge dieses Specs: 1. Implementation gemäß tasks.md (Remove UI Graph calls + Guard Tests) 2. Targeted Tests + Pint 3. Erst danach optional: eigener Spec für “job-based orchestration” (queued preview/execution) Co-authored-by: Ahmed Darrazi <ahmeddarrazi@adsmac.local> Reviewed-on: #54
5.1 KiB
Feature Specification: Backup/Restore UI Graph-Safety (Phase 1)
Feature Branch: feat/048-backup-restore-ui-graph-safety
Created: 2026-01-10
Status: Draft
Purpose
Ensure Backup/Restore UI follows the same guardrails as Inventory:
- UI renders DB-only (no Microsoft Graph calls during render/mount/options/typeahead)
- UI still remains usable with safe fallbacks for unresolved external identifiers
- Add programmatic guard tests that fail if Graph is touched while rendering
This phase is intentionally minimal-change and high-safety.
Clarifications
Session 2026-01-10
- Q: Which pages must the fail-hard
GraphClientInterfaceguard tests render? → A: Backup Sets index + Restore wizard. - Q: How should
<masked-id>be formatted in fallback labels? → A:…<last8>
Session 2026-01-11
- Q: How should the fail-hard Graph guard tests be structured? → A: Feature tests that
actingAs(...)thenGETthe Filament pages’ routes. - Q: For the feature tests, should we assert only HTTP 200, or also a stable UI marker? → A: Assert HTTP 200 + a stable page marker string.
Users
- Tenant Admin
- MSP Operator (within authorized tenant scope)
User Stories
US1 (P1): Backup Sets Index is Graph-safe
As a tenant admin, I can open the Backup Sets index page and it renders DB-only (no Graph calls during request/render/mount/options/typeahead).
Maps to: Scenario 1
US2 (P1): Restore Wizard is Graph-safe incl. Group Mapping UI
As a tenant admin, I can open the Restore wizard page and the group mapping UI remains usable without any Graph calls (including typeahead/search/label resolution).
Maps to: Scenario 2 + Scenario 3
User Scenarios & Testing
Scenario 1: Open Backup pages without Graph access
- Given a user is authenticated and has access to a tenant
- When they open the Backup Sets index page
- Then the page renders successfully (HTTP 200) without any Graph calls
Scenario 2: Open Restore Wizard without Graph access
- Given a user is authenticated and has access to a tenant
- When they open the Restore Run wizard page
- Then the wizard renders successfully (HTTP 200) without any Graph calls
Scenario 3: Group mapping shows safe fallback labels
- Given the UI displays group IDs (e.g., in mapping fields)
- When the UI cannot resolve group names without Graph
- Then it shows safe fallback labels like:
Unresolved (…<last8>)Group (external): …<last8>
Stable Page Marker Rules (for Guard Tests)
Guard tests MUST assert a stable, static marker string in addition to HTTP 200.
Marker selection rules:
- MUST be static UI text that is not tenant data (avoid names, IDs, timestamps, counts)
- SHOULD be a column label, section heading, or primary action label rendered by Filament
- MUST be present on the initial GET without requiring any Livewire interaction
- MUST NOT depend on Microsoft Graph availability
Markers MUST be recorded in quickstart.md once chosen.
Functional Requirements
- FR-001: Backup/Restore UI MUST NOT call Microsoft Graph during render/mount/options/typeahead.
- FR-002: The Restore Wizard group mapping controls MUST NOT call Graph for search results or label resolution.
Group Mapping UX (DB-only)
When group mapping is required, the UI MUST remain Graph-free and MUST provide a DB-only safe input.
-
For each unresolved source group, the UI shows a mapping row with:
- Source label:
<displayName or "Security group"> (…<last8>) - Target input:
- Allowed values:
SKIP(skip assignment)- A manually entered Entra ID group objectId (GUID/UUID string)
- Allowed values:
- Source label:
-
Validation rules:
- If not
SKIP, the value MUST be a syntactically valid UUID - No network lookup/verification is performed in Phase 1 (Graph-free). Existence is validated later during preview/restore execution paths.
- If not
-
Helper text MUST explain:
- “Paste the target Entra ID group Object ID (GUID). Names are not resolved in this phase.”
- “Use SKIP to omit the assignment.”
-
FR-003: When names cannot be resolved DB-only, the UI MUST show safe fallback labels using masked identifiers.
<masked-id>format:…<last8>(last 8 characters of the external identifier, prefixed with an ellipsis)
-
FR-004: Add fail-hard Pest feature tests binding
GraphClientInterfaceto throw on any invocation and verify:- Backup Sets index renders OK (HTTP 200 + stable page marker)
- Restore wizard renders OK (HTTP 200 + stable page marker)
Non-Functional Requirements
- NFR-001: No new Graph calls are introduced in UI code paths.
- NFR-002: No new tables are added in this phase.
- NFR-003: Changes should be low-risk and minimal surface area.
Out of Scope
- Moving action handlers (snapshot capture, backup create, restore rerun, restore dry-run) to jobs.
- Creating new cache/inventory tables to support group search.
Success Criteria
- SC-001: Guard tests reliably fail if any Backup/Restore UI render path touches Graph.
- SC-002: Backup and Restore wizard pages render successfully with Graph disabled.
- SC-003: Group mapping UI remains usable with DB-only fallback labels.
Related Specs
- Follow-up (Phase 2): Backup/Restore job orchestration (TBD)