# Feature Specification: Settings Foundation (Workspace + Optional Tenant Override) **Feature Branch**: `097-settings-foundation` **Created**: 2026-02-15 **Status**: Draft **Input**: User description: "Settings Foundation (Workspace + optional Tenant override)" ## Spec Scope Fields *(mandatory)* - **Scope**: workspace (with optional tenant overrides for future expansion) - **Primary Routes**: Admin panel “Settings” page (workspace-scoped) - **Data Ownership**: Workspace-owned settings records, with optional tenant override records that must belong to the same workspace - **RBAC**: Workspace membership required (non-members see 404); capability-gated view vs manage (Owner/Manager manage; Operator/Readonly view) ## Clarifications ### Session 2026-02-15 - Q: Which role-to-capability mapping should this spec enforce for workspace settings? → A: Option A (Owner+Manager manage; Operator+Readonly view) - Q: What should the system default be for `backup.retention_keep_last_default`? → A: Option A (`30`) - Q: Should `SettingsResolver` implement cross-request caching in v1? → A: Option A (request-local cache only) - Q: When a manager clicks “Reset to system default”, what should happen to the stored workspace override? → A: Option A (remove the override so resolution falls back to system default) ## User Scenarios & Testing *(mandatory)* ### User Story 1 - Manage workspace settings safely (Priority: P1) Workspace administrators need a single, consistent place to configure workspace-wide defaults that are used by operational features and can be audited later. **Why this priority**: Without a settings foundation, features will implement ad-hoc settings patterns that are inconsistent, hard to audit, and risky to operate. **Independent Test**: A manager updates the pilot setting, sees the new value reflected, and the system uses it as the workspace default for relevant behavior. **Acceptance Scenarios**: 1. **Given** a workspace member with settings-manage capability, **When** they update the pilot setting value, **Then** the value is persisted for that workspace and an audit entry is recorded. 2. **Given** a workspace member with settings-manage capability and an existing workspace override, **When** they reset the pilot setting to the system default, **Then** the effective value becomes the system default and an audit entry is recorded. --- ### User Story 2 - View settings without the ability to change them (Priority: P2) Read-only operators need to see what the workspace defaults are, without being able to modify them. **Why this priority**: Visibility supports troubleshooting and governance without expanding write privileges. **Independent Test**: A viewer can open the settings page and see values, but cannot persist any changes. **Acceptance Scenarios**: 1. **Given** a workspace member with settings-view capability but without settings-manage capability, **When** they open the settings page, **Then** they can view the current value but cannot save or reset settings. 2. **Given** a workspace member without settings-manage capability, **When** they attempt to submit a settings change by any means, **Then** the request is rejected with 403 and no setting is changed. --- ### User Story 3 - Tenant overrides take precedence (backend-ready) (Priority: P3) Some settings may need tenant-specific overrides while still inheriting workspace defaults when no override exists. **Why this priority**: Establishes a stable precedence model early, so future features can safely add tenant overrides without redefining rules. **Independent Test**: For a chosen tenant in a workspace, resolving a setting returns tenant override when present, otherwise workspace override, otherwise system default. **Acceptance Scenarios**: 1. **Given** no stored values for a setting, **When** the system resolves it for a workspace (and optional tenant), **Then** the system default is returned. 2. **Given** a workspace override exists, **When** the system resolves the setting, **Then** the workspace value is returned. 3. **Given** a tenant override exists within the same workspace, **When** the system resolves the setting for that tenant, **Then** the tenant value is returned even if a workspace value exists. ### Edge Cases - Unknown setting keys: write attempts are rejected and no changes are persisted. - Invalid values (wrong type / out-of-range): write attempts are rejected and no changes are persisted. - Tenant/workspace mismatch: the system rejects any attempt to store or resolve a tenant override for a tenant outside the workspace. - Concurrent updates: the last accepted update wins, and each accepted mutation results in exactly one audit entry. - Caching: within a single request, repeated reads for the same (workspace, optional tenant, domain, key) do not cause repeated database reads; across requests, no external cache is used in v1. ## Requirements *(mandatory)* **Constitution alignment (required):** This feature introduces workspace-scoped settings mutations that intentionally do not create an operational run record. Each successful settings mutation MUST be auditable via an audit entry, including who changed what and when. **Constitution alignment (RBAC-UX):** - Authorization planes: workspace-scoped admin panel surface. - 404 vs 403 semantics: - non-member / not entitled to the workspace scope → 404 (deny-as-not-found) - member but missing manage capability for mutations → 403 - Server-side enforcement: all setting mutations (update/reset) MUST be authorization-checked server-side; UI visibility/disabled states are not sufficient. **Role mapping (clarified):** - Owners and Managers MUST have settings-manage capability. - Operators and Readonly members MUST have settings-view capability. ### Functional Requirements - **FR-001**: System MUST provide a single settings substrate that can store workspace-wide defaults. - **FR-002**: System MUST support optional tenant overrides that are always scoped to the same workspace. - **FR-003**: System MUST resolve setting values using the precedence order: tenant override → workspace override → system default. - **FR-004**: System MUST reject writes for unknown setting keys. - **FR-005**: System MUST validate setting values against centrally-defined rules and reject invalid values. - **FR-006**: System MUST ensure settings data cannot be read or written across workspace boundaries. - **FR-007**: System MUST record an audit entry for each successful settings update and each successful reset-to-default. - **FR-008**: System MUST provide a workspace-scoped Settings UI surface that supports viewing and managing settings based on capabilities. - **FR-009**: System MUST include a pilot setting: `backup.retention_keep_last_default`. - **FR-010**: The pilot setting MUST define a system default of `30` (preserves current behavior), and it MUST be overrideable at workspace scope. - **FR-011**: When the pilot setting is used by backup scheduling/retention behavior, per-schedule overrides (if present) MUST continue to take precedence over workspace defaults. - **FR-012**: The settings resolver MUST implement request-local caching for resolved values within a single request. - **FR-013**: A reset-to-default MUST remove the stored override for the setting scope so future resolution falls back to the system default. ## 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 | |---|---|---|---|---|---|---|---|---|---|---| | Settings Page | Admin panel (workspace scope) | Save, Reset to system default | N/A | N/A | N/A | N/A | N/A | N/A | Yes | Reset is destructive-like and requires explicit confirmation; non-members get 404; members without manage get 403 on mutation | ### Key Entities *(include if feature involves data)* - **Setting Definition**: A centrally-defined (domain, key) entry that declares the system default and validation constraints. - **Workspace Setting Value**: A stored override for a (domain, key) at workspace scope. - **Tenant Setting Value**: A stored override for a (domain, key) at tenant scope within the same workspace. - **Settings Audit Entry**: An immutable record of a settings update or reset, including actor identity, target workspace/tenant, and before/after values. ### Non-Functional Requirements - **NFR-001 (Security / Isolation)**: Non-members MUST receive deny-as-not-found (404) for workspace settings surfaces. - **NFR-002 (Authorization)**: Members without the required capability MUST receive 403 for forbidden mutations. - **NFR-003 (Auditability)**: 100% of successful updates and resets MUST create an audit entry including actor, scope, and before/after values. - **NFR-004 (Data minimization)**: Audit entries MUST NOT include secrets or sensitive raw payloads. - **NFR-005 (Performance)**: Within a single request, repeated resolutions of the same setting scope MUST not require repeated database reads. ## Success Criteria *(mandatory)* ### Measurable Outcomes - **SC-001**: An authorized manager can update the pilot setting, and the Settings UI shows the new effective value after saving and persists it across a page reload. - **SC-002**: A viewer can open the Settings UI and see current values, and cannot persist changes (mutation attempts are rejected). - **SC-003**: Non-members cannot discover the Settings UI surface for a workspace (requests return 404). - **SC-004**: 100% of successful setting updates/resets create an audit entry that includes actor, scope (workspace + optional tenant), and before/after values.