## 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
65 lines
6.9 KiB
Markdown
65 lines
6.9 KiB
Markdown
# Research: Backup Quality Truth Surfaces
|
|
|
|
## Decision 1: Derive backup quality from existing backup and version metadata instead of creating a persisted backup-health model
|
|
|
|
- Decision: Build backup quality from the metadata already present on `BackupItem` and `PolicyVersion`, then aggregate backup-set truth from those per-item facts. Do not add a new table, column, or stored backup-health projection.
|
|
- Rationale: The current data model already records the core quality signals this feature needs: metadata-only source markers, assignment fetch failures, orphaned assignments, warnings, scope-tag context, and integrity notes. The product problem is weak surfacing, not missing persistence.
|
|
- Alternatives considered:
|
|
- Persist a `backup_quality` or `backup_health` table. Rejected because it would create a second source of truth for information that is already derivable.
|
|
- Add materialized quality fields to `backup_sets` or `policy_versions`. Rejected because the feature does not need independent lifecycle state.
|
|
|
|
## Decision 2: Keep capture lifecycle and backup quality as separate truths on every affected surface
|
|
|
|
- Decision: Render capture lifecycle (`completed`, `partial`, `failed`, `archived`) independently from backup quality (`metadata-only present`, `assignment issues present`, degraded-count summary, or no degradations detected).
|
|
- Rationale: Operators currently overread `completed` as `good backup`. The feature must stop that conflation without erasing the lifecycle truth that the system already tracks.
|
|
- Alternatives considered:
|
|
- Blend quality into one stronger status badge. Rejected because that would collapse two different truths into one ambiguous state.
|
|
- Treat `completed` plus degraded counts as a new status family. Rejected because it would introduce new state where derived summary is sufficient.
|
|
|
|
## Decision 3: Reuse the central snapshot-mode badge and shared badge infrastructure instead of page-local mapping
|
|
|
|
- Decision: Use the existing `BadgeDomain::PolicySnapshotMode` and `PolicySnapshotModeBadge` semantics for `full` versus `metadata only`. Any new quality chips or labels should stay inside shared badge or copy seams rather than page-local `match` statements.
|
|
- Rationale: The codebase already centralizes status-like badge semantics, and Filament v5 tables or schema text badges can render those shared specs directly. This keeps backup quality aligned with BADGE-001 and avoids a second vocabulary for snapshot completeness.
|
|
- Alternatives considered:
|
|
- Add local badge mapping per surface. Rejected because it would drift from the central badge catalog.
|
|
- Introduce a generic trust score badge. Rejected because the spec explicitly avoids a new scoring engine.
|
|
|
|
## Decision 4: Use existing Filament tables, infolists, enterprise-detail sections, and checkbox-list descriptions instead of a new UI shell
|
|
|
|
- Decision: Implement the feature inside `BackupSetResource`, `BackupItemsRelationManager`, `PolicyVersionResource`, and `RestoreRunResource` using the current Filament table columns, infolist sections, enterprise-detail builder, and wizard descriptions.
|
|
- Rationale: Filament v5 already supports badge columns, summary-first view content, relation-manager tables, and descriptive checkbox list options. The repository also already uses `enterpriseDetailPage()` for backup-set detail and schema-driven wizard steps for restore selection.
|
|
- Alternatives considered:
|
|
- Build a dedicated backup-health dashboard. Rejected because it is explicitly out of scope.
|
|
- Add a custom client-side wizard overlay. Rejected because the needed truth is server-driven and fits existing Filament seams.
|
|
|
|
## Decision 5: Surface backup-set and item quality in restore selection before risk checks, but keep restore safety as a separate authority
|
|
|
|
- Decision: Enrich restore wizard step 1 backup-set labels or helper copy and step 2 item descriptions with input-quality truth before preview or risk checks run. Do not block degraded selections at this stage unless existing restore safety already blocks them later.
|
|
- Rationale: Operators need early warning before the risk-check stage, but this spec is about backup quality, not execution safety. The restore-safety layer already owns blocker and preview-only semantics.
|
|
- Alternatives considered:
|
|
- Leave degraded truth exclusively to restore risk checks. Rejected because it preserves the current late-discovery trust failure.
|
|
- Prevent selecting degraded inputs in step 1 or step 2. Rejected because the spec requires truthful surfacing, not a new restore policy.
|
|
|
|
## Decision 6: Preserve truth visibility for `TENANT_VIEW` users even when restore actions remain unavailable
|
|
|
|
- Decision: Quality truth remains visible on backup-set and policy-version surfaces for users who can view tenant backup or version records, even if they cannot create restore runs or use maintenance actions.
|
|
- Rationale: Missing restore permission must not make degraded inputs appear calmer or cleaner. Authorization can suppress mutation, but it must not suppress source-of-truth visibility.
|
|
- Alternatives considered:
|
|
- Couple quality sections to restore permissions. Rejected because it would falsify the operator surface.
|
|
- Rely on disabled restore actions as the quality indicator for lower-privilege users. Rejected because disabled actions are not an adequate explanation of input quality.
|
|
|
|
## Decision 7: Use `unknown quality` only when existing metadata cannot justify a stronger claim
|
|
|
|
- Decision: Emit `unknown quality` only when the record lacks authoritative metadata for snapshot completeness or assignment-quality interpretation. Absence of an error is not enough to call an item or version `full` if the record never captured the relevant quality signal.
|
|
- Rationale: Defaulting to `unknown` too often would hide real degradations, while defaulting to `full` from silence would overstate confidence. This feature needs a narrow, evidence-based fallback.
|
|
- Alternatives considered:
|
|
- Default all older records to `unknown`. Rejected because many records already carry usable source metadata.
|
|
- Infer `full` whenever `metadata_only` is absent. Rejected because silence is not always proof of completeness.
|
|
|
|
## Decision 8: Extend the existing Pest and Livewire test surface rather than introducing a browser-first harness
|
|
|
|
- Decision: Add focused unit coverage for backup-quality derivation and extend existing backup, version, restore-selection, and RBAC feature tests for UI truth. Keep the current Pest and Livewire patterns as the main verification path.
|
|
- Rationale: The affected behavior is server-driven list, detail, and wizard state, which the current test suite already covers well. The repo also already has restore and RBAC tests that should remain authoritative.
|
|
- Alternatives considered:
|
|
- Rely only on manual validation. Rejected because the feature is specifically about preventing subtle trust regressions.
|
|
- Introduce a large browser-only test pack. Rejected because the most important assertions are deterministic server-side state and rendered truth. |