# Data Model: Backup/Restore UI Graph-Safety (048) This phase introduces **no schema changes**. It hardens UI render boundaries and adds guard tests. ## Existing Entities (used by this feature) ### Tenant - Purpose: Tenancy boundary for all reads/writes. - Notes: - Filament panel is tenant-scoped via `external_id` slug. ### User - Purpose: Authenticated actor; has tenant memberships/roles. ### BackupSet (`backup_sets`) - Fields (selected): - `id`, `tenant_id` - `name`, `created_by`, `status`, `item_count`, `completed_at` - `metadata` (JSON) - `deleted_at` (soft deletes, via housekeeping migration) - Indexes: `tenant_id,status`, `completed_at` - Used in UI: - Backup Sets index (table rendering must be DB-only) ### BackupItem (`backup_items`) - Fields (selected): - `id`, `tenant_id`, `backup_set_id` - `policy_id` (nullable), `policy_version_id` (nullable) - `policy_identifier`, `policy_type`, `platform` - `captured_at` - `payload` (JSON), `metadata` (JSON), `assignments` (JSON) - `deleted_at` (soft deletes) - Constraints: - Unique: `(backup_set_id, policy_identifier, policy_type)` - Used in UI: - Restore wizard item selection + metadata display (must not resolve external names via Graph) ### RestoreRun (`restore_runs`) - Fields (selected): - `id`, `tenant_id`, `backup_set_id` - `requested_by`, `is_dry_run`, `status` - `requested_items` (JSON), `preview` (JSON), `results` (JSON) - `group_mapping` (JSON) - `failure_reason`, `started_at`, `completed_at`, `metadata` (JSON) - `deleted_at` (soft deletes) - Used in UI: - Restore wizard render (Create page) including group mapping controls ## Relationships (high-level) - `Tenant` has many `BackupSet`, `BackupItem`, `RestoreRun`. - `BackupSet` has many `BackupItem`. - `RestoreRun` belongs to `BackupSet`. ## Validation & State Transitions (relevant to this phase) - No new state transitions introduced. - The key invariant enforced by tests: - Rendering Backup/Restore UI pages must not invoke `GraphClientInterface`.