TenantAtlas/specs/048-backup-restore-ui-graph-safety/spec.md
ahmido b35e3a6518 spec: refine 048 guardrails (#54)
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
2026-01-10 23:37:22 +00:00

128 lines
5.1 KiB
Markdown
Raw Permalink 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)