## Summary - add a shared backup-quality resolver and summary model for backup sets, backup items, policy versions, and restore selection - surface backup-quality truth across Filament backup-set, policy-version, and restore-wizard entry points - add focused Pest coverage and the full Spec Kit artifact set for spec 176 ## Testing - focused backup-quality verification and integrated-browser smoke coverage were completed during implementation - degraded browser smoke path was validated with temporary seeded records and then cleaned up again - the workspace already has a prior `vendor/bin/sail artisan test --compact` run exiting non-zero; that full-suite failure was not reworked as part of this PR Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #211
12 KiB
Data Model: Backup Quality Truth Surfaces
Overview
This feature does not add or change a top-level persisted domain entity. It introduces a tighter derived backup-quality model around the existing tenant-owned backup, version, and restore-selection surfaces.
The central design task is to make existing backup truth visible without changing:
BackupSet,BackupItem, orPolicyVersionownership- existing backup or restore route identity
- existing restore-safety, preview, and execution authority
- existing audit and RBAC responsibilities
- the no-new-table boundary of this feature
Existing Persistent Entities
1. BackupSet
- Purpose: Tenant-owned backup collection that records lifecycle state and groups captured backup items.
- Existing persistent fields used by this feature:
idtenant_idnamestatusitem_countmetadatacreated_bycompleted_atcreated_at
- Existing relationships used by this feature:
tenantitemsrestoreRuns
Proposed nested metadata additions
None. Backup-set quality is derived from related backup items and existing set facts. No new backup-set status or metadata field is required.
2. BackupItem
- Purpose: Tenant-owned captured recovery input for one backed-up policy or foundation record.
- Existing persistent fields used by this feature:
idtenant_idbackup_set_idpolicy_idpolicy_version_idpolicy_identifierpolicy_typeplatformpayloadassignmentsmetadatacaptured_at
- Existing relationships used by this feature:
tenantbackupSetpolicypolicyVersion
Existing metadata signals used by this feature
| Key | Type | Meaning |
|---|---|---|
source |
string or null | Primary source marker; may be metadata_only |
snapshot_source |
string or null | Copied source marker from a linked policy version when a backup item is created from a version |
warnings |
array | Warning messages; may include metadata-only fallback wording |
assignments_fetch_failed |
boolean | Assignment capture failed for this item |
assignment_capture_reason |
string or null | Informational reason such as separate_role_assignments; not all reasons are degradations |
has_orphaned_assignments |
boolean | One or more resolved assignment targets were orphaned |
assignment_count |
integer or null | Captured assignment count |
scope_tag_ids |
array<int | string> |
scope_tag_names |
array | Captured scope-tag names |
integrity_warning |
string or null | Existing integrity or redaction warning copied into the backup item |
protected_paths_count |
integer or null | Count of protected or redacted paths copied from the policy version context |
3. PolicyVersion
- Purpose: Tenant-owned immutable version record for a policy snapshot.
- Existing persistent fields used by this feature:
idtenant_idpolicy_idversion_numbersnapshotmetadataassignmentsscope_tagssecret_fingerprintsredaction_versioncaptured_atcapture_purpose
- Existing relationships used by this feature:
tenantpolicyoperationRun
Existing metadata signals used by this feature
| Key | Type | Meaning |
|---|---|---|
source |
string or null | Snapshot source marker; metadata_only is the primary degraded completeness signal |
warnings |
array | Snapshot warnings; may include metadata-only fallback language |
assignments_fetch_failed |
boolean | Assignment capture failed during version capture |
assignments_fetch_error |
string or null | Human-readable assignment capture error |
assignments_fetch_error_code |
int or string or null | Technical assignment capture error code |
has_orphaned_assignments |
boolean | One or more captured assignment targets were orphaned |
capture_source |
string or null | Existing capture context such as version_capture |
Related persisted integrity context used by this feature
| Field | Type | Meaning |
|---|---|---|
secret_fingerprints |
array | Existing redaction context used to expose integrity notes on version-derived restore inputs |
redaction_version |
integer | Existing redaction version for operator diagnostics |
scope_tags |
array | Existing scope-tag context surfaced alongside quality truth where useful |
4. Restore selection context
- Purpose: Existing wizard state that lets operators choose a backup set and optional backup-item subset before running risk checks.
- Existing state used by this feature:
backup_set_idscope_modebackup_item_idsgroup_mappingis_dry_run
No new persisted restore-selection state is planned. This feature only enriches the current rendered option models.
Derived Models
1. SnapshotCompletenessFact
Derived completeness truth shared by backup items and policy versions.
| Field | Type | Source | Notes |
|---|---|---|---|
mode |
string | metadata-derived | full, metadata_only, or unknown |
sourceSignal |
string or null | metadata.source or metadata.snapshot_source |
Authoritative direct signal when present |
warningEvidence |
list | metadata.warnings |
Secondary fallback signal |
badgeState |
string | derived | Routes to the existing PolicySnapshotModeBadge state |
Rules:
metadata_onlywhensourceorsnapshot_sourceequalsmetadata_only, or when warning evidence clearly states metadata-only capture.fullonly when there is no metadata-only evidence and the record contains enough captured payload context to justify a complete-snapshot claim.unknownonly when existing metadata cannot prove eitherfullormetadata_only.
2. AssignmentCaptureFact
Derived assignment-quality truth for backup items and policy versions.
| Field | Type | Source | Notes |
|---|---|---|---|
fetchFailed |
boolean | assignments_fetch_failed |
Primary degraded assignment signal |
captureReason |
string or null | assignment_capture_reason |
Informational reason; not always degraded |
orphanedAssignments |
boolean | has_orphaned_assignments |
Secondary degraded signal |
assignmentCount |
integer or null | assignment_count or assignments length |
Informational support data |
issuePresent |
boolean | derived | True when fetch failed or orphaned targets exist |
Rules:
assignment_capture_reason = separate_role_assignmentsis informative and must not be misread as a failure on its own.fetchFailed = trueis a degraded quality signal.orphanedAssignments = trueis a degraded quality signal even if fetch succeeded.
3. BackupItemQualityFact
Default item-level backup-quality model for backup items.
| Field | Type | Source | Notes |
|---|---|---|---|
backupItemId |
integer | record id | Identity |
snapshotCompleteness |
SnapshotCompletenessFact |
derived | Primary completeness truth |
assignmentCapture |
AssignmentCaptureFact |
derived | Assignment quality truth |
integrityWarning |
string or null | metadata.integrity_warning |
Existing integrity signal |
degradationFamilies |
list | derived | Examples: metadata_only, assignment_capture_issue, orphaned_assignments, integrity_warning, unknown_quality |
hasDegradations |
boolean | derived | True when one or more degradation families apply |
summaryMessage |
string | derived | Concise operator-facing truth |
nextAction |
string | derived | Primary next step such as inspect detail or continue with caution |
4. BackupSetQualitySummary
Aggregate backup-quality truth for one backup set.
| Field | Type | Source | Notes |
|---|---|---|---|
backupSetId |
integer | record id | Identity |
totalItems |
integer | item_count or related count |
Informational total |
degradedItemCount |
integer | aggregated item facts | Number of degraded items |
metadataOnlyCount |
integer | aggregated item facts | Count of metadata-only items |
assignmentIssueCount |
integer | aggregated item facts | Count of assignment capture failures |
orphanedAssignmentCount |
integer | aggregated item facts | Count of orphaned-assignment signals |
integrityWarningCount |
integer | aggregated item facts | Count of integrity warnings carried into backup items |
unknownQualityCount |
integer | aggregated item facts | Count of items whose quality is truly unknown |
degradationFamilies |
list | derived | Set-level union of degradation families |
summaryMessage |
string | derived | Compact summary for list and detail |
nextAction |
string | derived | Open detail, inspect degraded items, prefer stronger version, or continue with caution |
positiveClaimBoundary |
string | derived | Explains that quality does not equal safe restore or tenant recoverability |
Rules:
- Aggregate counts are computed from related
BackupItemQualityFactvalues, never fromBackupSet.status. completed but degradedremains a display combination of lifecycle plus quality summary, not a new persisted backup-set status.
5. PolicyVersionQualityFact
Version-level backup-quality truth for policy versions.
| Field | Type | Source | Notes |
|---|---|---|---|
policyVersionId |
integer | record id | Identity |
snapshotCompleteness |
SnapshotCompletenessFact |
derived from version metadata | Primary completeness truth |
assignmentCapture |
AssignmentCaptureFact |
derived from version metadata and assignments | Assignment quality truth |
integrityWarning |
string or null | derived from existing redaction or integrity context | Existing warning already present in current restore and version flows |
degradationFamilies |
list | derived | Same family as backup items where applicable |
hasDegradations |
boolean | derived | True when one or more degradation families apply |
summaryMessage |
string | derived | Concise operator-facing truth |
nextAction |
string | derived | Prefer stronger version, inspect raw settings, or continue to restore with caution |
6. RestoreSelectionQualityHint
Selection-stage quality model for restore wizard step 1 and step 2.
| Field | Type | Source | Notes |
|---|---|---|---|
targetType |
string | derived | backup_set or backup_item |
targetId |
integer | selected record id | Identity |
summaryMessage |
string | derived | Early warning before risk checks |
degradationFamilies |
list | derived | Carries through set-level or item-level truth |
nextAction |
string | derived | Inspect detail or continue with caution |
positiveClaimBoundary |
string | derived | Explicitly states that input quality is not restore safety |
Rules:
- Step 1 uses
BackupSetQualitySummaryfacts. - Step 2 uses
BackupItemQualityFactfacts. - Neither step may claim
safe to restore,restore ready, ortenant recoverable.
Validation Rules
- Never derive backup quality from
BackupSet.status,PolicyVersionaction availability, or restore gating alone. assignments_fetch_failedandhas_orphaned_assignmentsare distinct signals and must be surfaced separately where the UI can support it.assignment_capture_reasonis explanatory metadata, not automatically a degraded state.unknown qualityis permitted only when current metadata cannot justifyfullormetadata_onlyand cannot justify an assignment-quality claim.TENANT_VIEWvisibility for backup-quality truth must remain independent fromTENANT_MANAGErestore capability.- Restore selection hints must explicitly preserve the claim boundary that backup quality is not restore safety.