Skip to content

Settings Scope Precedence ​

Settings in the SDK are scoped: the same setting key can carry a different value at each scope level, and the runtime resolves them in a fixed precedence order.

A setting's detail with its existing scope overrides, and the form for adding one at tenant scope.
One setting, its overrides per scope, and the form that adds another. The lock marks a scope this actor may not write.

The five scopes ​

The ladder is Core's Scope enum (LaravelUi5\Core\Parameters\Enums\Scope), from least to most specific:

ScopeMeaning
PlatformThe default declared in code, seeded by ui5:sync (least specific)
InstallationShared override, written by an operator admin
TenantShared override, written by a tenant admin or above
SiteShared override, written by a local admin or above
UserPersonal override for one partner (most specific)

Each shared scope holds at most one value per setting. The rows carry no tenant or site id: one installation is one tenant (Tenancy). Who may write which scope is on Reading & Writing.

Resolution order ​

Platform < Installation < Tenant < Site < User

When the runtime asks "what is the value of approval.threshold for this artifact?", the highest scope present wins. A User value wins over a Site value, a Site value over a Tenant value, and so on down to the Platform default.

User is the only personal scope. A read sees every shared row (Platform to Site) plus the current actor's own User rows, never another partner's.

This means:

  • Defaults live at Platform. Declare a setting with Core's #[Setting] attribute; ui5:sync writes its default as the Platform row. That row belongs to code: the settings writer refuses Scope::Platform, so a default changes only when its declaration changes.
  • Overrides live above it. Writing at Installation, Tenant, Site or User is gated by the setting's edit level and by which scopes the actor's system level may write.
  • Resetting an override deletes that one row, and the value falls back to the next scope present.

Storage ​

All settings live in a single table, sdk_settings, one row per artifact, scope, key and (for User scope) partner:

ColumnMeaning
artifact_idthe artifact the setting belongs to (FK → sdk_artifacts.id)
settingthe key (the semantic name)
scopetinyint holding the Scope value
partner_idthe owning partner (FK → sdk_partners.id, cascade on delete); set only for User scope
set_bythe partner who last wrote the row; the system actor for the seeded Platform row
valuethe JSON-encoded value
value_typeCore ValueType; see Type Validation
levelCore EditLevel, the minimum level allowed to edit the setting
value_help, value_help_scopethe value-help picker bound to a Model-typed setting
model_classthe Eloquent model class of a Model-typed setting

Reading a setting ​

Your code reads a setting with SdkContext::setting() and gets the value that wins for the acting partner. Which artifact's settings a request sees is on Reading & Writing.

See also ​