# 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.