Settings Manifest Settings Manifest protocol schemas
Settings Manifest Protocol
Declarative description of a single namespace of platform settings
(e.g. mail, branding, feature_flags). Modelled on Apple's
Settings.bundle/Root.plist PreferenceSpecifiers — a small, closed
set of specifier types that the system-owned renderer turns into a
uniform Settings page.
Storage for values is the generic sys_setting K/V table; manifests
themselves are NEVER persisted — they ship with plugin code.
See ADR-0007 (Settings Manifest + K/V Store + Resolver).
Resolution order (handled by SettingsService.get):
process.env override (source='env', locked=true)
sys_setting scope=tenant
sys_setting scope=user
manifest specifier.default
Source: packages/spec/src/system/settings-manifest.zod.ts
import { ResolvedSettingValueSchema, SettingsActionResultSchema, SettingsManifestSchema, SettingsNamespacePayloadSchema, SpecifierSchema, SpecifierHandlerSchema, SpecifierOptionSchema, SpecifierScopeSchema, SpecifierType, SpecifierValueDomainSchema } from '@objectstack/spec/system' ;
import type { ResolvedSettingValue, SettingsActionResult, SettingsManifest, SettingsNamespacePayload, Specifier, SpecifierHandler, SpecifierOption, SpecifierScope, SpecifierType, SpecifierValueDomain } from '@objectstack/spec/system' ;
// Validate data
const result = ResolvedSettingValueSchema. parse (data);
Property Type Required Description value any✅ Effective value (post-resolution) source Enum<'env' | 'global' | 'tenant' | 'user' | 'default'>✅ Resolution source locked boolean✅ Cannot be overridden from UI lockedReason stringoptional Reason for the lock (UI tooltip) cascadeChain { scope: Enum<'env' | 'global' | 'tenant' | 'user' | 'default'>; value: any; locked?: boolean; lockedReason?: string; … }[]optional Full cascade trace (env → global → tenant → user → default)
Property Type Required Description ok boolean✅ Success flag message stringoptional Toast message severity Enum<'info' | 'success' | 'warning' | 'error'>optional details anyoptional Optional structured detail (renderer-defined)
Property Type Required Description namespace string✅ Namespace (snake_case, globally unique) version integeroptional Manifest schema version label string | Record<string, string>✅ Display label icon stringoptional Icon (Lucide) description stringoptional Short description helpText stringoptional Markdown help text shown above specifiers scope Enum<'global' | 'tenant' | 'user'>optional Default scope for specifiers readPermission stringoptional Permission required to read writePermission stringoptional Permission required to write category stringoptional Settings hub category order numberoptional Display order specifiers { type: Enum<'group' | 'child_pane' | 'info_banner' | 'title_value' | 'text' | 'textarea' | … +13 more>; id?: string; key?: string; label: string | Record<string, string>; … }[]✅ Page contents (ordered) visible string | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optional Whole-manifest visibility. Grammar is NOT CEL: root data with one-level member access, || && !, === !== == != >= <= > <, parentheses and string/number/bool/null literals, optionally wrapped in ${...}; bare string or { dialect, source } envelope. featureFlag stringoptional Gate manifest visibility on a feature flag beta booleanoptional Show a Beta chip on the page
Property Type Required Description manifest { namespace: string; version?: integer; label: string | Record<string, string>; icon?: string; … }✅ values Record<string, { value: any; source: Enum<'env' | 'global' | 'tenant' | 'user' | 'default'>; locked: boolean; lockedReason?: string; … }>✅ Effective values keyed by specifier.key
Property Type Required Description type Enum<'group' | 'child_pane' | 'info_banner' | 'title_value' | 'text' | 'textarea' | 'password' | 'email' | 'url' | 'phone' | 'number' | 'toggle' | 'select' | 'radio' | … +5 more>✅ Specifier variant id stringoptional Stable identifier (snake_case) key stringoptional Storage key (snake_case) label string | Record<string, string>✅ Display label description stringoptional Help text icon stringoptional Icon name (Lucide) default anyoptional Default value visible string | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optional Visibility expression evaluated against the namespace value map, e.g. ${data.provider === 'smtp'}. Hidden specifiers are not rendered and their values are not validated. Grammar is NOT CEL: root data with one-level member access, || && !, === !== == != >= <= > <, parentheses and string/number/bool/null literals, optionally wrapped in ${...}; bare string or { dialect, source } envelope. required booleanoptional Required field encrypted booleanoptional Encrypt value at rest (forced true for password) scope Enum<'global' | 'tenant' | 'user'>optional Override manifest scope for this key availableScopes Enum<'global' | 'tenant' | 'user'>[]optional Scopes allowed to override this specifier lockable booleanoptional Allow upper-scope locking of this specifier readPermission stringoptional Permission required to read this specifier writePermission stringoptional Permission required to write this specifier deprecated booleanoptional Mark deprecated replacedBy stringoptional Replacement key (used when deprecated=true) options { value: string | number | boolean; label: string | Record<string, string>; description?: string; icon?: string }[]optional Options for select/radio/multiselect valueDomain Enum<'iana_time_zone' | 'iso_4217_currency' | 'iso_3166_alpha2'>optional Standard value domain enforced on write (options degrade to a UI suggestion list) min numberoptional max numberoptional step numberoptional minLength integeroptional maxLength integeroptional pattern stringoptional Regex pattern (text only) rows integeroptional handler { kind: 'http'; method?: Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'>; url: string; body?: Record<string, any>; … } | { kind: 'action'; name: string; params?: Record<string, any>; confirmText?: string | Record<string, string> } | { kind: 'navigate'; url: string; target?: Enum<'_self' | '_blank'> }optional Action handler (action_button) childNamespace stringoptional Sub-namespace (child_pane) bannerText stringoptional Markdown body (info_banner) bannerSeverity Enum<'info' | 'success' | 'warning' | 'error'>optional
group
child_pane
info_banner
title_value
text
textarea
password
email
url
phone
number
toggle
select
radio
multiselect
slider
color
json
action_button
This schema accepts one of the following structures:
Property Type Required Description kind 'http'✅ method Enum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'>✅ url string✅ Endpoint URL; supports ${...} interpolation body Record<string, any>optional Optional JSON body; supports ${...} interpolation confirmText string | Record<string, string>optional Confirm dialog text before invoking (omit = no confirm)
Property Type Required Description kind 'action'✅ name string✅ Registered action machine name params Record<string, any>optional confirmText string | Record<string, string>optional Display label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time
Property Type Required Description kind 'navigate'✅ url string✅ Target URL or in-app route target Enum<'_self' | '_blank'>✅
Property Type Required Description value string | number | boolean✅ Stored value label string | Record<string, string>✅ Display label description stringoptional Optional helper text icon stringoptional Optional Lucide icon name
group
child_pane
info_banner
title_value
text
textarea
password
email
url
phone
number
toggle
select
radio
multiselect
slider
color
json
action_button
iana_time_zone
iso_4217_currency
iso_3166_alpha2