TenantAtlas/specs/048-backup-restore-ui-graph-safety/research.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

46 lines
2.5 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.

# Research: Backup/Restore UI Graph-Safety (048)
## Decision: Enforce Graph-safety via fail-hard feature renders
- **Decision**: Add Pest *feature* tests that `actingAs(...)` and `GET` Filament page URLs while binding `App\Services\Graph\GraphClientInterface` to a fail-hard implementation (throws on any call).
- **Rationale**: A full HTTP render exercises the real Filament request lifecycle (middleware, tenancy, resource/page boot) and will fail immediately if any UI render path touches Graph.
- **Alternatives considered**:
- Livewire component tests only → can miss route/middleware/tenancy boot and wont reflect “real render” regressions as reliably.
- Binding Graph to `NullGraphClient` → would allow silent Graph usage to slip through.
## Decision: Use `Resource::getUrl()` for stable Filament routes (tenant-scoped)
- **Decision**: Use Filaments URL helpers in tests:
- `BackupSetResource::getUrl('index', tenant: $tenant)`
- `RestoreRunResource::getUrl('create', tenant: $tenant)`
- **Rationale**: Avoids hardcoding route paths and keeps tests resilient to panel path / tenancy prefix changes.
- **Repo evidence**:
- `tests/Feature/Filament/InventorySyncRunResourceTest.php` uses `->get(InventorySyncRunResource::getUrl('index', tenant: $tenant))`.
- **Alternatives considered**:
- Hardcoded `/admin/t/{tenant}/...` paths → brittle if the panel path or tenant prefix changes.
## Decision: Assert HTTP 200 + stable marker
- **Decision**: Guard tests assert `->assertOk()` plus a stable marker string per page.
- **Rationale**: Reduces false positives (e.g., a redirect to login) and makes failures easier to diagnose.
- **Alternatives considered**:
- Status-only (200) → may still pass with empty/partial output or wrong page.
## Decision: Fallback label masking format
- **Decision**: Mask unresolved external IDs as `…<last8>` (last 8 characters, prefixed with ellipsis).
- **Rationale**: Keeps UI readable while avoiding full identifier disclosure.
- **Alternatives considered**:
- Full ID → increases accidental disclosure.
- Hash → less readable for operators.
## Decision: Filament panel + tenancy routing assumptions
- **Decision**: Treat the Filament admin panel as tenant-scoped under the configured path/prefix:
- Panel path: `admin`
- Tenant route prefix: `t`
- Tenant slug attribute: `external_id`
- **Rationale**: This is the repos current canonical setup (`App\Providers\Filament\AdminPanelProvider`).
- **Alternatives considered**:
- Non-tenant-scoped pages → not applicable (TenantPilot is tenant-first).