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

5.1 KiB
Raw Blame History

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.
  • Follow-up (Phase 2): Backup/Restore job orchestration (TBD)