ObjectStackObjectStack

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):

  1. process.env override (source='env', locked=true)
  2. sys_setting scope=tenant
  3. sys_setting scope=user
  4. manifest specifier.default

Source: packages/spec/src/system/settings-manifest.zod.ts

TypeScript Usage

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);

ResolvedSettingValue

Properties

PropertyTypeRequiredDescription
valueanyEffective value (post-resolution)
sourceEnum<'env' | 'global' | 'tenant' | 'user' | 'default'>Resolution source
lockedbooleanCannot be overridden from UI
lockedReasonstringoptionalReason for the lock (UI tooltip)
cascadeChain{ scope: Enum<'env' | 'global' | 'tenant' | 'user' | 'default'>; value: any; locked?: boolean; lockedReason?: string; … }[]optionalFull cascade trace (env → global → tenant → user → default)

SettingsActionResult

Properties

PropertyTypeRequiredDescription
okbooleanSuccess flag
messagestringoptionalToast message
severityEnum<'info' | 'success' | 'warning' | 'error'>optional
detailsanyoptionalOptional structured detail (renderer-defined)

SettingsManifest

Properties

PropertyTypeRequiredDescription
namespacestringNamespace (snake_case, globally unique)
versionintegeroptionalManifest schema version
labelstring | Record<string, string>Display label
iconstringoptionalIcon (Lucide)
descriptionstringoptionalShort description
helpTextstringoptionalMarkdown help text shown above specifiers
scopeEnum<'global' | 'tenant' | 'user'>optionalDefault scope for specifiers
readPermissionstringoptionalPermission required to read
writePermissionstringoptionalPermission required to write
categorystringoptionalSettings hub category
ordernumberoptionalDisplay 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)
visiblestring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optionalWhole-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.
featureFlagstringoptionalGate manifest visibility on a feature flag
betabooleanoptionalShow a Beta chip on the page

SettingsNamespacePayload

Properties

PropertyTypeRequiredDescription
manifest{ namespace: string; version?: integer; label: string | Record<string, string>; icon?: string; … }
valuesRecord<string, { value: any; source: Enum<'env' | 'global' | 'tenant' | 'user' | 'default'>; locked: boolean; lockedReason?: string; … }>Effective values keyed by specifier.key

Specifier

Properties

PropertyTypeRequiredDescription
typeEnum<'group' | 'child_pane' | 'info_banner' | 'title_value' | 'text' | 'textarea' | 'password' | 'email' | 'url' | 'phone' | 'number' | 'toggle' | 'select' | 'radio' | … +5 more>Specifier variant
idstringoptionalStable identifier (snake_case)
keystringoptionalStorage key (snake_case)
labelstring | Record<string, string>Display label
descriptionstringoptionalHelp text
iconstringoptionalIcon name (Lucide)
defaultanyoptionalDefault value
visiblestring | { dialect: Enum<'cel' | 'cron' | 'template'>; source?: string; ast?: any; meta?: object }optionalVisibility 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.
requiredbooleanoptionalRequired field
encryptedbooleanoptionalEncrypt value at rest (forced true for password)
scopeEnum<'global' | 'tenant' | 'user'>optionalOverride manifest scope for this key
availableScopesEnum<'global' | 'tenant' | 'user'>[]optionalScopes allowed to override this specifier
lockablebooleanoptionalAllow upper-scope locking of this specifier
readPermissionstringoptionalPermission required to read this specifier
writePermissionstringoptionalPermission required to write this specifier
deprecatedbooleanoptionalMark deprecated
replacedBystringoptionalReplacement key (used when deprecated=true)
options{ value: string | number | boolean; label: string | Record<string, string>; description?: string; icon?: string }[]optionalOptions for select/radio/multiselect
valueDomainEnum<'iana_time_zone' | 'iso_4217_currency' | 'iso_3166_alpha2'>optionalStandard value domain enforced on write (options degrade to a UI suggestion list)
minnumberoptional
maxnumberoptional
stepnumberoptional
minLengthintegeroptional
maxLengthintegeroptional
patternstringoptionalRegex pattern (text only)
rowsintegeroptional
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'> }optionalAction handler (action_button)
childNamespacestringoptionalSub-namespace (child_pane)
bannerTextstringoptionalMarkdown body (info_banner)
bannerSeverityEnum<'info' | 'success' | 'warning' | 'error'>optional

Allowed Values: Specifier.type

  • group
  • child_pane
  • info_banner
  • title_value
  • text
  • textarea
  • password
  • email
  • url
  • phone
  • number
  • toggle
  • select
  • radio
  • multiselect
  • slider
  • color
  • json
  • action_button

SpecifierHandler

Union Options

This schema accepts one of the following structures:

Option 1

Properties

PropertyTypeRequiredDescription
kind'http'
methodEnum<'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'>
urlstringEndpoint URL; supports ${...} interpolation
bodyRecord<string, any>optionalOptional JSON body; supports ${...} interpolation
confirmTextstring | Record<string, string>optionalConfirm dialog text before invoking (omit = no confirm)

Option 2

Properties

PropertyTypeRequiredDescription
kind'action'
namestringRegistered action machine name
paramsRecord<string, any>optional
confirmTextstring | Record<string, string>optionalDisplay label — the default-language string, or an inline locale map ({ en, "zh-CN" }) resolved at render time

Option 3

Properties

PropertyTypeRequiredDescription
kind'navigate'
urlstringTarget URL or in-app route
targetEnum<'_self' | '_blank'>


SpecifierOption

Properties

PropertyTypeRequiredDescription
valuestring | number | booleanStored value
labelstring | Record<string, string>Display label
descriptionstringoptionalOptional helper text
iconstringoptionalOptional Lucide icon name

SpecifierScope

Allowed Values

  • global
  • tenant
  • user

SpecifierType

Allowed Values

  • group
  • child_pane
  • info_banner
  • title_value
  • text
  • textarea
  • password
  • email
  • url
  • phone
  • number
  • toggle
  • select
  • radio
  • multiselect
  • slider
  • color
  • json
  • action_button

SpecifierValueDomain

Allowed Values

  • iana_time_zone
  • iso_4217_currency
  • iso_3166_alpha2

On this page