Tenant Settings Hardening
Tenant settings hardening
Tenant settings are resolved from generated defaults in config/mortimer.yml and optional tenant overrides in storage/tenants/:slug/config.yml.
Roles and authority
- Tenant roles are currently
memberandadmin. - Settings changes (module/capability toggles and presentation preference writes) are currently done through admin-protected routes.
- There is currently no separate
superuserrole in tenant settings, and no special permission tier for team leads.
Effective config caching
- Effective config reads are cached by tenant slug and config file signatures.
- Cache entries are invalidated after tenant settings writes.
- This keeps repeated reads fast while ensuring fresh values after changes.
Version migration path
- Config resolution runs a migration pipeline before validation.
- Overrides without a version are migrated to the current schema version.
- Unsupported future versions fail fast with a validation error.
Audit trail
- Each tenant settings write persists a
ConfigChangeEvent. - Events include tenant, optional actor identity, event type, context, and before/after override payloads.
- Export bundles include
config_change_events.csvfor archived tenant recovery/audit workflows.
Behavior FAQ
What happens when an admin disables a module?
- Requests into controllers guarded by that module are blocked by
ModuleGuardand return404 Not Found. - This is intentional to hide disabled surfaces rather than exposing a partial page with errors.
- Re-enabling the module restores access for users in that tenant.
What happens when an admin disables a capability inside a module?
- Requests to guarded actions are blocked by
CapabilityGuardand return404 Not Found. - Example: task quick-start, reorder, and pause/resume/stop actions are individually capability-guarded.
- Capability checks require both the module and the capability to be enabled.
Which preferences can memberships set today?
- Current write path supports membership-level dashboard preference:
dashboard.compact_widgets
- In current UI/controller flow, this is changed through admin-only membership management routes.
If a team lead sets a team preference, does it affect all team members?
- Team preferences are resolved as team-scope overrides and are merged into membership presentation resolution for members of those teams.
- In current permissions, team preference writes are admin-only; there is no dedicated team-lead write permission.
- Membership-specific overrides are applied after team overrides and therefore win if both set the same key.
Who is a superuser?
- Tenant settings currently do not define a
superuserrole. - Operationally, the highest tenant-scoped authority is
adminmembership for the tenant.
Can an admin hide fields on members' edit views?
- Not as a generalized tenant-setting for all member edit forms today.
- The config model contains task field metadata (
tasks.fields) for visibility/required semantics, but broad per-view field visibility toggles for member edit pages are not currently exposed as an admin feature. - If needed, this should be treated as a new story with explicit scope (which views, which fields, and whether hidden vs read-only behavior is required).