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
TypeScript Usage
import { ResolvedSettingValue, SettingsActionResult, SettingsManifest, SettingsNamespacePayload, Specifier, SpecifierHandler, SpecifierOption, SpecifierScope, SpecifierType } from '@objectstack/spec/system';
import type { ResolvedSettingValue, SettingsActionResult, SettingsManifest, SettingsNamespacePayload, Specifier, SpecifierHandler, SpecifierOption, SpecifierScope, SpecifierType } from '@objectstack/spec/system';
// Validate data
const result = ResolvedSettingValue.parse(data);ResolvedSettingValue
Properties
| 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 | string | optional | Reason for the lock (UI tooltip) |
| cascadeChain | Object[] | optional | Full cascade trace (env → global → tenant → user → default) |
SettingsActionResult
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| ok | boolean | ✅ | Success flag |
| message | string | optional | Toast message |
| severity | Enum<'info' | 'success' | 'warning' | 'error'> | optional | |
| details | any | optional | Optional structured detail (renderer-defined) |
SettingsManifest
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| namespace | string | ✅ | Namespace (snake_case, globally unique) |
| version | integer | optional | Manifest schema version |
| label | string | ✅ | Display label |
| icon | string | optional | Icon (Lucide) |
| description | string | optional | Short description |
| helpText | string | optional | Markdown help text shown above specifiers |
| scope | Enum<'global' | 'tenant' | 'user'> | optional | Default scope for specifiers |
| readPermission | string | optional | Permission required to read |
| writePermission | string | optional | Permission required to write |
| category | string | optional | Settings hub category |
| order | number | optional | Display order |
| specifiers | Object[] | ✅ | Page contents (ordered) |
| visible | string | Object | optional | Whole-manifest visibility |
| featureFlag | string | optional | Gate manifest visibility on a feature flag |
| beta | boolean | optional | Show a Beta chip on the page |
SettingsNamespacePayload
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| manifest | Object | ✅ | |
| values | Record<string, Object> | ✅ | Effective values keyed by specifier.key |
Specifier
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| type | Enum<'group' | 'child_pane' | 'info_banner' | 'title_value' | 'text' | 'textarea' | 'password' | 'email' | 'url' | 'phone' | 'number' | 'toggle' | 'select' | 'radio' | 'multiselect' | 'slider' | 'color' | 'json' | 'action_button'> | ✅ | Specifier variant |
| id | string | optional | Stable identifier (snake_case) |
| key | string | optional | Storage key (snake_case) |
| label | string | ✅ | Display label |
| description | string | optional | Help text |
| icon | string | optional | Icon name (Lucide) |
| default | any | optional | Default value |
| visible | string | Object | optional | Visibility expression |
| required | boolean | optional | Required field |
| encrypted | boolean | optional | 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 | boolean | optional | Allow upper-scope locking of this specifier |
| readPermission | string | optional | Permission required to read this specifier |
| writePermission | string | optional | Permission required to write this specifier |
| deprecated | boolean | optional | Mark deprecated |
| replacedBy | string | optional | Replacement key (used when deprecated=true) |
| options | Object[] | optional | Options for select/radio/multiselect |
| min | number | optional | |
| max | number | optional | |
| step | number | optional | |
| minLength | integer | optional | |
| maxLength | integer | optional | |
| pattern | string | optional | Regex pattern (text only) |
| rows | integer | optional | |
| handler | Object | Object | Object | optional | Action handler (action_button) |
| childNamespace | string | optional | Sub-namespace (child_pane) |
| bannerText | string | optional | Markdown body (info_banner) |
| bannerSeverity | Enum<'info' | 'success' | 'warning' | 'error'> | optional |
SpecifierHandler
Union Options
This schema accepts one of the following structures:
Option 1
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| kind | string | ✅ | |
| 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 | optional | Confirm dialog text before invoking (omit = no confirm) |
Option 2
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| kind | string | ✅ | |
| name | string | ✅ | Registered action machine name |
| params | Record<string, any> | optional | |
| confirmText | string | optional | Display label (plain string; i18n keys are auto-generated by the framework) |
Option 3
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| kind | string | ✅ | |
| url | string | ✅ | Target URL or in-app route |
| target | Enum<'_self' | '_blank'> | ✅ |
SpecifierOption
Properties
| Property | Type | Required | Description |
|---|---|---|---|
| value | string | number | boolean | ✅ | Stored value |
| label | string | ✅ | Display label |
| description | string | optional | Optional helper text |
| icon | string | optional | Optional Lucide icon name |
SpecifierScope
Allowed Values
globaltenantuser
SpecifierType
Allowed Values
groupchild_paneinfo_bannertitle_valuetexttextareapasswordemailurlphonenumbertoggleselectradiomultiselectslidercolorjsonaction_button