Organization-Level Configuration Overrides #3419
dakshina99
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
What
Every platform-api setting is one value for the whole deployment: it comes from
config.toml(or a{{ env }}token) and applies identically to everyorganization. Some settings need to differ per organization. The first concrete
case is
deployments.max_builds_per_api— how many builds an API may keep —where different organizations are entitled to different limits. Today the only
way to express that is a code change or a separate deployment.
This proposes one generic override layer: an organization may carry a value for a
declared subset of config keys, and when it does, that value wins over the
file. Nothing else about configuration changes, and a deployment that sets no
overrides behaves exactly as it does now.
Precedence
Keys are the same dotted paths the file already uses
(
deployments.max_builds_per_api), so both sources share one key space andprecedence needs no mapping between them.
Table
Key/value rows rather than a column per setting: making a new setting
overridable is then a registry entry, not a schema migration. Values are stored
as text and parsed against the type the registry declares.
Registry — what may be overridden
Not every setting may be.
database.password,security.encryption_key,listener ports and the auth configuration are properties of the deployment; an
organization-scoped write to any of them is an escalation, not a preference. So
overridable keys are declared, and anything not declared is refused — an
allowlist, not a denylist:
The definition carries the type and its bounds, so a bad value is rejected at the
write rather than discovered at the read, where there is nothing sensible to do
with it.
Reading it
Resolution goes through one seam, so no call site can reach for
cfg.Xand anoverride at the same time and get a different answer than its neighbour:
These reads sit on hot paths — every build and every deploy — so the resolver
caches per organization with a short TTL. platform-api runs multiple replicas, so
a write cannot invalidate its peers' caches; a TTL bounds how long a stale value
can be in force instead of pretending the problem does not exist.
REST
New scopes
ap:organization:config:readandap:organization:config:manage,alongside the existing
ap:organization:*. The listing reports each key'seffective value and its source (
organizationorplatform), so a console canshow what is actually in force without knowing anything about the config file.
Scope of the first PR
deployments.max_builds_per_api, switched to resolvethrough the resolver instead of reading the config struct directly.
Every other setting keeps reading the file until it is registered, so the change
is additive.
Open questions
DELETEof an unset key be a 404 or a no-op 204?All reactions