# Data Model — Settings Foundation (Workspace + Optional Tenant Override) (097) ## Entities ### SettingDefinition (code-defined) Represents a known (domain, key) setting with validation, normalization, and a system default. - Fields (conceptual): - `domain` (string) - `key` (string) - `type` (enum-like: int|string|bool|json) - `system_default` (mixed) - `rules` (validation rules; code-level) - `normalize(value) -> value` (optional) ### WorkspaceSetting (DB: workspace-owned) A workspace-wide override for a setting. - Table: `workspace_settings` - Fields: - `id` - `workspace_id` (FK → `workspaces.id`, NOT NULL) - `domain` (string, NOT NULL) - `key` (string, NOT NULL) - `value` (JSON/JSONB, NOT NULL) - `updated_by_user_id` (FK → `users.id`, nullable) - timestamps - Indexes / constraints: - UNIQUE (`workspace_id`, `domain`, `key`) - Index (`workspace_id`, `domain`) ### TenantSetting (DB: tenant-owned; backend-ready) A tenant-specific override for a setting. - Table: `tenant_settings` - Fields: - `id` - `workspace_id` (FK → `workspaces.id`, NOT NULL) - `tenant_id` (FK → `tenants.id`, NOT NULL) - `domain` (string, NOT NULL) - `key` (string, NOT NULL) - `value` (JSON/JSONB, NOT NULL) - `updated_by_user_id` (FK → `users.id`, nullable) - timestamps - Indexes / constraints: - UNIQUE (`tenant_id`, `domain`, `key`) - Index (`workspace_id`, `tenant_id`) ## Relationships - Workspace has many WorkspaceSettings. - Workspace has many TenantSettings. - Tenant has many TenantSettings. ## Invariants / Rules enforced by this feature - Resolution precedence is deterministic: - tenant override → workspace override → system default. - Workspace isolation: - all reads/writes must be scoped to the active workspace context. - tenant overrides must be rejected if the tenant does not belong to the workspace. - Unknown keys are rejected: - writes must only be allowed for keys in the SettingsRegistry. - Validation is centralized: - values are validated against the SettingDefinition before persistence. - Reset semantics: - reset removes the persisted override row (workspace or tenant) so resolution falls back. ## Pilot Setting (v1) - Domain: `backup` - Key: `retention_keep_last_default` - Type: `int` - System default: `30` - Validation: - integer - minimum 1 (defensive)