Implements Spec 098: workspace-level settings slices for Backup retention, Drift severity mapping, and Operations retention/threshold. Spec - specs/098-settings-slices-v1-backup-drift-ops/spec.md What changed - Workspace Settings page: grouped Backup/Drift/Operations sections, unset-input UX w/ helper text, per-setting reset actions (confirmed) - Settings registry: adds/updates validation + normalization (incl. drift severity mapping normalization to lowercase) - Backup retention: adds workspace default + floor clamp; job clamps effective keep-last up to floor - Drift findings: optional workspace severity mapping; adds `critical` severity support + badge mapping - Operations pruning: retention computed per workspace via settings; scheduler unchanged; stuck threshold is storage-only Safety / Compliance notes - Filament v5 / Livewire v4: no Livewire v3 usage; relies on existing Filament v5 + Livewire v4 stack - Provider registration unchanged (Laravel 11+/12 uses bootstrap/providers.php) - Destructive actions: per-setting reset uses Filament actions with confirmation - Global search: not affected (no resource changes) - Assets: no new assets registered; no `filament:assets` changes Tests - vendor/bin/sail artisan test --compact tests/Feature/SettingsFoundation/WorkspaceSettingsManageTest.php \ tests/Feature/SettingsFoundation/WorkspaceSettingsViewOnlyTest.php \ tests/Feature/BackupScheduling/BackupScheduleLifecycleTest.php \ tests/Feature/Drift/DriftPolicySnapshotDriftDetectionTest.php \ tests/Feature/Scheduling/PruneOldOperationRunsScheduleTest.php \ tests/Unit/Badges/FindingBadgesTest.php Formatting - vendor/bin/sail bin pint --dirty Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #120
12 KiB
Feature Specification: 098 — Settings Slices v1 (Backup + Drift + Operations)
Feature Branch: 098-settings-slices-v1-backup-drift-ops
Created: 2026-02-16
Status: Draft
Input: Workspace-level settings slices for Backup, Drift severity mapping, and Operations retention/thresholds with safe defaults.
Spec Scope Fields (mandatory)
- Scope: workspace
- Primary Routes: Workspace Settings screen (admin UI)
- Data Ownership: workspace-owned settings values (key/value) + audit log entries for setting changes
- RBAC: workspace membership required; view vs manage capability-gated; deny-as-not-found for non-members
Clarifications
Session 2026-02-16
- Q: Which “Reset to default” scope do you want on the Workspace Settings UI? → A: Per-setting reset (each key individually).
- Q: When an admin clicks “Save” and multiple settings change at once, how should audit logging behave? → A: One audit log entry per key changed.
- Q: Should we enforce a validation constraint between
backup.retention_keep_last_defaultandbackup.retention_min_floor? → A: Allow any values; effective retention is always clamped tobackup.retention_min_floor. - Q: For settings that are currently unset (so the system uses defaults), how should the UI present them? → A: Leave input unset, show helper text with the default/effective value.
- Q: In
drift.severity_mapping, should severity values be case-sensitive? → A: Case-insensitive; normalize to lowercase on save.
User Scenarios & Testing (mandatory)
User Story 1 - Configure backup retention defaults (Priority: P1)
As a workspace admin, I want to configure workspace-wide defaults for backup retention so that enterprise workspaces can tune policy without code/config changes.
Why this priority: Backup retention is a common enterprise requirement and impacts storage cost and governance.
Independent Test: Can be tested by setting/unsetting workspace settings and verifying backup retention behavior remains unchanged by default and changes deterministically when configured.
Acceptance Scenarios:
- Given no workspace settings exist for backup retention, When a backup retention decision is made, Then behavior matches the current baseline (no change).
- Given a workspace default retention value is configured, When a backup retention decision is made without a more specific override, Then the configured default is used.
- Given a retention “floor” value is configured, When any calculated retention value is below the floor, Then the effective retention is clamped up to the floor.
- Given a per-schedule override is configured, When that override is below the configured floor, Then the override is clamped up to the floor.
User Story 2 - Configure drift severity mapping (Priority: P2)
As a workspace admin, I want to map drift finding types to severities so that findings align with enterprise risk posture and triage practices.
Why this priority: Severity directly affects how teams triage drift; a one-size-fits-all default is too rigid for enterprise.
Independent Test: Can be tested by saving a mapping, generating findings for mapped/unmapped types, and verifying severities are assigned correctly.
Acceptance Scenarios:
- Given no drift severity mapping exists, When a drift finding is produced, Then its severity defaults to “medium”.
- Given a mapping exists for a specific finding type, When a drift finding with that type is produced, Then the mapped severity is applied.
- Given a mapping contains an unknown/unsupported severity value, When an admin attempts to save it, Then the save is rejected and no invalid values are persisted.
User Story 3 - Configure operations retention and stuck threshold (Priority: P3)
As a workspace admin, I want to configure retention for operations/run records and store a “stuck run” threshold so that data lifecycle and operational heuristics are workspace-tunable.
Why this priority: Retention policies and operational thresholds vary widely between organizations and audit requirements.
Independent Test: Can be tested by saving retention/threshold settings and verifying the retention cutoff used by pruning changes accordingly while no new automatic actions occur.
Acceptance Scenarios:
- Given no operations retention setting exists, When operations/run pruning is executed, Then the cutoff matches the current baseline (no change).
- Given an operations retention setting exists, When pruning is executed, Then the cutoff is derived from the configured retention days.
- Given a stuck threshold is configured, When the Workspace Settings screen is re-opened, Then the configured value is shown exactly as saved.
- Given a stuck threshold is configured, When operations/run behavior is observed, Then no automatic remediation or auto-handling is performed in this feature scope.
Edge Cases
- Attempting to save invalid numeric ranges (too low/high) is rejected and does not persist.
- Attempting to save invalid JSON (malformed) for drift mapping is rejected.
- Attempting to save drift mapping with non-string keys is rejected.
- Two admins editing settings concurrently results in deterministic persisted state (last write wins) and both attempts are auditable.
- A user without manage capability can view settings (read-only) but cannot submit changes.
- A non-member cannot discover the Workspace Settings screen or any values (deny-as-not-found).
Requirements (mandatory)
Constitution alignment (required): This feature MUST remain DB-only for screen rendering and MUST NOT introduce Microsoft Graph calls as part of rendering or saving these settings. Any setting mutation MUST be auditable.
Dependencies & Assumptions
- This feature depends on an existing workspace settings foundation that provides: workspace-scoped storage, consistent defaults, centralized validation, RBAC capability enforcement, and audit logging for changes.
- No tenant-specific override UI is included in v1; only workspace-wide configuration is in scope.
- The default values for all settings keys match the current baseline behavior at the time this feature ships.
Constitution alignment (RBAC-UX):
- Authorization planes involved: workspace-scoped admin UI.
- Non-member / not entitled to workspace scope → 404 (deny-as-not-found).
- Member but missing manage capability → 403 on mutation attempts; UI remains read-only.
Constitution alignment (OPS/observability): This feature does not introduce a new long-running operation type; it changes which configuration values are used by existing behavior. All admin-initiated mutations MUST produce audit log entries.
Functional Requirements
- FR-001: System MUST support workspace-level configuration for the following setting keys:
backup.retention_keep_last_defaultbackup.retention_min_floordrift.severity_mappingoperations.operation_run_retention_daysoperations.stuck_run_threshold_minutes
- FR-002: System MUST preserve existing behavior when none of the above settings are configured (defaults MUST match the current baseline).
- FR-003: System MUST validate and reject invalid setting values, ensuring no invalid configuration is silently persisted.
- FR-004: Workspace Settings UI MUST present the above keys grouped into three sections (Backup, Drift, Operations) and MUST be fully functional without any external API calls.
- FR-004a: For any setting key that is currently unset, the UI MUST keep the input in an “unset” state and MUST display helper text indicating the default (currently effective) value.
- FR-005: Users with view capability MUST be able to view current effective settings but MUST NOT be able to change them.
- FR-006: Users with manage capability MUST be able to change settings and reset individual settings back to defaults.
- FR-007: Resetting a setting to default MUST be a confirmed (destructive-like) action.
- FR-008: System MUST write audit log entries for each settings update and reset-to-default event including: workspace identity, actor identity, setting key, old value, new value, and timestamp.
- FR-008a: When a single save operation changes multiple keys, the system MUST write one audit log entry per key changed.
Backup slice requirements
- FR-009:
backup.retention_keep_last_defaultMUST be an integer between 1 and 365. - FR-010:
backup.retention_min_floorMUST be an integer between 1 and 365. - FR-011: Effective backup retention MUST never be lower than
backup.retention_min_floor(applies to defaults and any more specific overrides). - FR-011a: The system MUST NOT reject configuration solely because
backup.retention_min_floorexceedsbackup.retention_keep_last_default; instead, the effective retention MUST be clamped to the floor.
Drift slice requirements
- FR-012:
drift.severity_mappingMUST be a JSON object mappingfinding_type(string) → severity. - FR-013: Allowed severity values MUST be limited to:
low,medium,high,critical. - FR-013a: Severity values MUST be accepted case-insensitively and normalized to lowercase when persisted.
- FR-014: If a finding type has no mapping entry, severity MUST default to
medium.
Operations slice requirements
- FR-015:
operations.operation_run_retention_daysMUST be an integer between 7 and 3650. - FR-016: Pruning of operations/run records MUST use the configured retention days when set; otherwise it MUST behave as the baseline.
- FR-017:
operations.stuck_run_threshold_minutesMUST be an integer between 0 and 10080. - FR-018:
operations.stuck_run_threshold_minutesMUST be a stored configuration value only; it MUST NOT introduce auto-remediation or auto-handling behavior in this feature scope.
UI Action Matrix (mandatory when Filament is changed)
| Surface | Location | Header Actions | Inspect Affordance (List/Table) | Row Actions (max 2 visible) | Bulk Actions (grouped) | Empty-State CTA(s) | View Header Actions | Create/Edit Save+Cancel | Audit log? | Notes / Exemptions |
|---|---|---|---|---|---|---|---|---|---|---|
| Page | Workspace Settings (admin UI) | Save; Reset setting to default (per-setting, confirmed) | N/A | N/A | N/A | N/A | N/A | Save + Cancel | Yes | View capability: read-only fields; Manage capability: editable + submit; Non-member: 404 |
Key Entities (include if feature involves data)
- Workspace Setting: A workspace-owned key/value configuration item with validation rules and a default.
- Audit Log Entry: An immutable record of a settings update or reset-to-default event.
- Drift Finding Type: A classification string used to identify the type of drift finding for severity mapping.
Success Criteria (mandatory)
Measurable Outcomes
- SC-001: When no settings are configured for these keys, backup retention behavior, drift severity behavior, and operations pruning behavior match the baseline in automated regression tests.
- SC-002: An authorized workspace admin can update each of the 5 settings and observe the new effective value reflected in the Workspace Settings screen immediately after save.
- SC-003: 100% of settings updates and reset-to-default actions produce an audit log entry with key, old value, and new value.
- SC-004: Invalid configuration attempts (out-of-range numbers, invalid JSON, unsupported severities) are rejected and do not change persisted settings.