## Summary - separate provider-missing policy presence from local ignore semantics by introducing `missing_from_provider_at` - update policy, backup, and restore surfaces so current-state capture stays honest while historical restore continuity remains available - add focused sync, Filament, backup, restore, localization, and badge coverage for the new provider-missing behavior ## Scope - policy sync and model truth - policy resource visibility, badges, labels, and action gating - backup/export eligibility and restore continuity messaging - spec 261 artifacts and focused tests ## Validation - feature-specific Pest coverage is included in the branch - validation was not re-run as part of this commit/push/PR handoff Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #316
5.9 KiB
5.9 KiB
Data Model: Provider-Missing Policy Visibility & Restore Continuity v1
Overview
This slice changes one existing persisted entity and introduces only derived projections elsewhere. No new table, registry, or artifact family is planned.
Entity: Policy (existing, modified)
Table: policies
Fields
| Field | Type | Source | Notes |
|---|---|---|---|
id |
bigint | existing | Primary key |
workspace_id |
bigint | existing | Required ownership anchor |
tenant_id |
bigint | existing | Required ownership anchor |
external_id |
string | existing | Provider-facing stable key |
policy_type |
string | existing | Canonical local policy type |
ignored_at |
timestamp nullable | existing | Explicit local suppression only after this slice |
missing_from_provider_at |
timestamp nullable | new | Provider-missing observation in the current supported provider-backed result set |
last_synced_at |
timestamp nullable | existing | Last successful provider observation/update on this row |
Invariants
workspace_idandtenant_idremain required and non-null.ignored_atmay only be set or cleared by explicit local suppression flows.missing_from_provider_atmay only be set or cleared by sync/provider-observation logic.- A policy row remains persisted and viewable even when
missing_from_provider_atis set.
Derived Visibility States
| Derived state | ignored_at |
missing_from_provider_at |
Meaning |
|---|---|---|---|
active |
null | null | Current policy is locally visible and currently observed in the provider-backed result set |
ignored_locally |
set | null | Current policy is intentionally hidden/suppressed locally |
provider_missing |
null | set | Current policy remains local truth but is not currently observed in the supported provider-backed result set |
ignored_locally_provider_missing |
set | set | Policy is locally suppressed and also currently missing from the provider-backed result set |
Filter Membership And Precedence
activefilter returns onlyactiverows.ignoredfilter returnsignored_locallyandignored_locally_provider_missingrows.provider_missingfilter returnsprovider_missingandignored_locally_provider_missingrows.allreturns the complete set.- For current backup/export,
provider_missingwins as the primaryblocked_reasonwhen both timestamps are present because fresh provider-backed capture is impossible even if the row is also locally ignored.
State Transition Rules
| Event | From | To | Notes |
|---|---|---|---|
| Local ignore | active or provider_missing |
ignored_locally or ignored_locally_provider_missing |
Explicit operator intent |
| Local restore/unignore | ignored_locally or ignored_locally_provider_missing |
active or provider_missing |
Clears only ignored_at |
| Sync marks missing | active or ignored_locally |
provider_missing or ignored_locally_provider_missing |
Sets only missing_from_provider_at |
| Sync reappears | provider_missing or ignored_locally_provider_missing |
active or ignored_locally |
Clears only missing_from_provider_at |
| Sync reclassifies to supported type | any provider-present state | provider-present state | Updates policy_type without using ignore semantics |
Derived Projection: Current Backup Eligibility
Persistence: none; computed from Policy
| Field | Type | Meaning |
|---|---|---|
policy_id |
bigint | Policy being evaluated for current backup/export |
eligible |
boolean | True only when the policy is neither locally ignored nor provider-missing for current-state capture |
blocked_reason |
string nullable | ignored_locally or provider_missing when not eligible; provider_missing wins when both timestamps are present |
historical_continuity_available |
boolean | Indicates whether backup history already exists even if current capture is blocked |
Rules
- Fresh provider-backed capture requires
ignored_at = nullandmissing_from_provider_at = null. - When both timestamps are set, current backup/export MUST return
blocked_reason = provider_missingand MUST retain local ignore as secondary UI context. - Historical backup existence does not make a provider-missing policy eligible for fresh capture.
Derived Projection: Restore Continuity
Persistence: none; computed from BackupItem plus optional linked Policy
| Field | Type | Meaning |
|---|---|---|
backup_item_id |
bigint | Historical item being offered for restore |
policy_id |
bigint nullable | Linked current policy row when present |
selectable |
boolean | Restore eligibility of the historical item |
provider_missing_notice |
boolean | Shows that the current live policy is missing while the historical item remains valid |
continuity_message |
string nullable | Calm explanation shown in restore selection |
Rules
- Historical restore selection continues to follow
BackupItemtruth. - Provider-missing status on the live policy is descriptive unless an independent restore rule blocks the historical item.
Audit Payload (existing infrastructure, new event meanings)
Persistence: existing audit_logs
| Field | Type | Meaning |
|---|---|---|
action_id |
string | policy.provider_missing_detected or policy.provider_missing_cleared or equivalent existing action ids if reused |
workspace_id |
bigint | Existing scope anchor |
tenant_id |
bigint | Existing scope anchor |
subject_type |
string | policy |
subject_id |
bigint | Policy id |
metadata.external_id |
string | Provider-facing stable key |
metadata.policy_type |
string | Canonical local policy type |
metadata.transition_at |
timestamp | When the presence transition was observed |
Out of Scope Data Shapes
- No
provider_deleted_at - No lifecycle history table
- No materialized
policy_stateenum column - No new recovery artifact or backup continuity table