Context
Products need Magento-style scoped configuration: a default, overridden by the platform, a tenant, a node in the scope tree and a user, with per-locale values. A single settings service would couple every service to it; per-service ad-hoc tables would give every service a different shape. The ported Figentra settings package has decorators and a registry, but its resolver assumes a flat scope. Deploy-time configuration (@stackra/config, 0044)
is a different thing and is not changed here.
Decision
- S1 — Ownership. Each service owns its setting values in a standard
settings_valuestable from@stackra/settings. The schema is declared with@Settingsand@Settingdecorators, lands in the gen manifest, and is held by the registry (0109). The admin BFF renders settings screens from it. - S2 — Scope chain: default → platform → tenant → scope-tree nodes (Pro) → user. Each field declares which scopes may set it. A higher scope can lock a field so lower scopes cannot override it, and a deploy can lock a field too.
- S3 — Locale. Fields may hold per-locale values. Locale, currency and time zone are themselves settings, resolved at the edge of the request.
- S4 — Credentials are never setting values; a setting holds a
@ConnectionRef(0107). - S5 — Storage: one row per key, scope and locale.
- S6 — Encryption applies only to settings whose values are PII-class.
- S7 — Caching: a per-tenant version counter, a
settings.changed.v1event, and an LRU or shared cache in front. - S8 — Cross-service reads use the request context or an event-fed projection, never a synchronous call to another service’s settings.
- S9 — User preferences are split by owning service, like any other setting.
- S10 — Export and import is JSON per service or group.
- S11 — Schema evolution is
@SettingsMigration. - S12 — The Pro ltree scope tree stays, overriding the Tenant document’s decision to drop the Scope service.
- The Figentra settings resolver is rewritten for this chain; its decorators and registry are ported.
Consequences
- Every service gets the same settings shape and screens without a central settings service.
- The scope-node level exists only where
@stackra-pro/scopeis installed; free installs stop at tenant then user. - Settings schemas become part of the manifest review surface.
Enforcement
Planned: asettings_values RLS isolation test in @stackra/settings; the gen validation pass fails a @Setting without a
scope list or a secret-typed setting without @ConnectionRef. Nothing checks this today.