Settings edition gating
StudioBrain’s settings registry uses an edition field to keep shared settings in core while allowing product-specific surfaces to add their own sections without leaking commercial or desktop-only UI into other builds.
Contract
The canonical contract is SettingsEdition in frontend/src/lib/settings-registry.ts:
type SettingsEdition = 'core' | 'cloud' | 'desktop' | 'mobile';Each SettingsSection may set edition. An omitted value behaves like core.
| Section edition | Visible in |
|---|---|
omitted or core | core, cloud, desktop, and mobile |
cloud | cloud only |
desktop | desktop only |
mobile | mobile only |
getVisibleSections(scope, edition, isAdmin) first filters by scope, then applies this edition rule, then applies requiresAdmin. isSectionVisible uses the same rule for a single section. Callers must pass the active edition; relying on the default deliberately produces the core-safe view.
Overlay boundary
Keep portable settings definitions and components in studiobrain-core. Commercial implementations belong in their owning overlay repository. An overlay may extend the shared registry or supply the component named by a gated section, but core must not import the overlay.
Use edition: 'cloud' for SaaS-only sections and edition: 'desktop' for native-only sections. Do not use edition gating as an authorization check: sensitive routes still require backend authentication and authorization. requiresAdmin is a presentation filter, not a substitute for server-side policy.
Add a gated section
{
id: 'account',
label: 'Account',
icon: Building,
scope: 'account',
edition: 'cloud',
component: 'AccountsIframe',
}When adding a section:
- Put portable metadata in the shared registry and implementation-specific UI in the owning overlay.
- Set the narrowest correct
edition; omit it only when every edition can render the section. - Add the component to the settings renderer for the editions that expose it.
- Test both sides of the gate: the intended edition sees it, and at least one other edition does not.
- If it is admin-only, also test
requiresAdminindependently of edition.
The source of truth is frontend/src/lib/settings-registry.ts. Update this guide when the union or filtering rules change.