ADR-0002 — Parameters registry with scope hierarchy
**Status.** Accepted.
Status. Accepted. Date. 2026-05-18.
Context
A multi-tenant Telegram platform has thousands of values that may need to differ per environment, tier, client, target, chat, route, userbot or persona — and that may need to change without a deploy. Env vars and YAML configs cannot express this without an explosion of files and restarts.
Decision
Every tunable is registered in core/settings/parameters.py as a
Parameter(...). Each parameter declares its type, default, bounds, allowed
values, scope levels, audit sensitivity and hot-reload topic.
Overrides are stored in a single settings_overrides table (append-only,
hash-chained for audit). The resolver walks the scope hierarchy from most
specific to least specific and returns the first override that exists.
The admin Mini App auto-renders forms from the parameters manifest.
Consequences
- New tunables are one entry, never a migration or a deploy.
- Owners can change anything for any scope, any time, with full audit.
- Hot reload is universal: any process's resolver cache is invalidated via Redis Pub/Sub on every override write.
- Mistakes in scope/type/bounds are caught at write time by validators.
- Stealth-critical knobs have hard ceilings that cannot be loosened.
Alternatives considered
- LaunchDarkly / Flagsmith. Rejected: too heavy, no scope hierarchy, vendor lock-in, off-platform secret transit.
- etcd / Consul. Rejected: no audit, no scope hierarchy, ops cost.
- Per-feature ad-hoc tables. Rejected: drift between tables and admin UI.