Proposal to adopt a user-settings architecture as a stack pattern (proven in a downstream project; reference links kept internal).
The pattern:
- One
userSettings row per user, every field optional; no row until first write.
- One read query applying defaults from a code-side
DEFAULTS object — clients never null-check, defaults change without migration.
- One write mutation
settings.set({ setting: { key, value } }) with a per-key discriminated union: granular one-setting-per-call writes, value typed to its key, future side effects are a switch case not a sibling mutation.
- UI: up to three surfaces over the one store — a /settings page that always shows everything, promoted shortcuts (avatar menu), inline controls at the point of effect. Promote by frequency-of-change × proximity-of-effect.
- Scope: per-user cross-device preferences only; per-device state stays client-side.
Adding a setting = optional schema field + DEFAULTS entry + union member + a row on /settings.
Scope if accepted: add an ADR + a minimal settings module (one example setting) to the template.
Proposal to adopt a user-settings architecture as a stack pattern (proven in a downstream project; reference links kept internal).
The pattern:
userSettingsrow per user, every field optional; no row until first write.DEFAULTSobject — clients never null-check, defaults change without migration.settings.set({ setting: { key, value } })with a per-key discriminated union: granular one-setting-per-call writes, value typed to its key, future side effects are aswitchcase not a sibling mutation.Adding a setting = optional schema field + DEFAULTS entry + union member + a row on /settings.
Scope if accepted: add an ADR + a minimal settings module (one example setting) to the template.