TenantAtlas/specs/048-backup-restore-ui-graph-safety/spec.md
2026-01-11 00:35:29 +01:00

128 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 `GraphClientInterface` guard 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(...)` then `GET` the 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)
- 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.
- 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 `GraphClientInterface` to 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)