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)