Skip to main content

mz_adapter_types/
dyncfgs.rs

1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10//! Dyncfgs used by the adapter layer.
11
12use std::time::Duration;
13
14use mz_dyncfg::{Config, ConfigSet};
15
16pub const ALLOW_USER_SESSIONS: Config<bool> = Config::new(
17    "allow_user_sessions",
18    true,
19    "Whether to allow user roles to create new sessions. When false, only system roles will be permitted to create new sessions.",
20);
21
22// Slightly awkward with the WITH prefix, but we can't start with a 0..
23pub const WITH_0DT_DEPLOYMENT_MAX_WAIT: Config<Duration> = Config::new(
24    "with_0dt_deployment_max_wait",
25    // One year, which in practice makes it so we never cut over when not
26    // hydrated. To prevent cutting over unilaterally when there is an issue.
27    Duration::from_hours(365 * 24),
28    "How long to wait at most for clusters to be hydrated, when doing a zero-downtime deployment.",
29);
30
31pub const WITH_0DT_DEPLOYMENT_DDL_CHECK_INTERVAL: Config<Duration> = Config::new(
32    "with_0dt_deployment_ddl_check_interval",
33    Duration::from_secs(5 * 60),
34    "How often to check for DDL changes during zero-downtime deployment.",
35);
36
37pub const ENABLE_0DT_DEPLOYMENT_PANIC_AFTER_TIMEOUT: Config<bool> = Config::new(
38    "enable_0dt_deployment_panic_after_timeout",
39    false,
40    "Whether to panic if the maximum wait time is reached but preflight checks have not succeeded.",
41);
42
43pub const WITH_0DT_DEPLOYMENT_CAUGHT_UP_CHECK_INTERVAL: Config<Duration> = Config::new(
44    // The feature flag name is historical.
45    "0dt_deployment_hydration_check_interval",
46    Duration::from_secs(10),
47    "Interval at which to check whether clusters are caught up, when doing zero-downtime deployment.",
48);
49
50pub const WITH_0DT_CAUGHT_UP_CHECK_ALLOWED_LAG: Config<Duration> = Config::new(
51    "with_0dt_caught_up_check_allowed_lag",
52    Duration::from_secs(60),
53    "Maximum allowed lag when determining whether collections are caught up for 0dt deployments.",
54);
55
56pub const WITH_0DT_CAUGHT_UP_CHECK_CUTOFF: Config<Duration> = Config::new(
57    "with_0dt_caught_up_check_cutoff",
58    Duration::from_secs(2 * 60 * 60), // 2 hours
59    "Collections whose write frontier is behind 'now' by more than the cutoff are ignored when doing caught-up checks for 0dt deployments.",
60);
61
62pub const ENABLE_0DT_CAUGHT_UP_REPLICA_STATUS_CHECK: Config<bool> = Config::new(
63    "enable_0dt_caught_up_replica_status_check",
64    true,
65    "Enable checking for crash/OOM-looping replicas during 0dt caught-up checks. Emergency break-glass flag to disable this feature if needed.",
66);
67
68// TODO(aljoscha): Remove this break-glass flag after a couple of releases, once
69// the sustained-health gate has proven itself in production. It only exists as a
70// fleet-wide automatic revert to the prior "caught-up implies ready" behavior.
71pub const ENABLE_0DT_CAUGHT_UP_STABILITY_CHECK: Config<bool> = Config::new(
72    "enable_0dt_caught_up_stability_check",
73    true,
74    "Require clusters to stay caught-up and healthy for a stability period before being considered ready during 0dt deployments. Emergency break-glass flag: disabling reverts to treating a caught-up cluster as ready with no replica-health requirement, which differs from setting the stability period to zero (a zero period still requires all replicas to be healthy).",
75);
76
77pub const WITH_0DT_CAUGHT_UP_CHECK_STABILITY_PERIOD: Config<Duration> = Config::new(
78    "with_0dt_caught_up_check_stability_period",
79    Duration::from_secs(10 * 60), // 10 minutes
80    "How long a cluster must continuously be caught-up and have all replicas healthy before it is considered ready to cut over during a 0dt deployment.",
81);
82
83/// Enable logging of statement lifecycle events in mz_internal.mz_statement_lifecycle_history.
84pub const ENABLE_STATEMENT_LIFECYCLE_LOGGING: Config<bool> = Config::new(
85    "enable_statement_lifecycle_logging",
86    true,
87    "Enable logging of statement lifecycle events in mz_internal.mz_statement_lifecycle_history.",
88);
89
90/// Enable installation of introspection subscribes.
91pub const ENABLE_INTROSPECTION_SUBSCRIBES: Config<bool> = Config::new(
92    "enable_introspection_subscribes",
93    true,
94    "Enable installation of introspection subscribes.",
95);
96
97/// Enable sending subscribes down the new frontend-peek path.
98pub const ENABLE_FRONTEND_SUBSCRIBES: Config<bool> = Config::new(
99    "enable_frontend_subscribes",
100    true,
101    "Enable sending subscribes down the new frontend-peek path.",
102);
103
104/// The plan insights notice will not investigate fast path clusters if plan optimization took longer than this.
105pub const PLAN_INSIGHTS_NOTICE_FAST_PATH_CLUSTERS_OPTIMIZE_DURATION: Config<Duration> = Config::new(
106    "plan_insights_notice_fast_path_clusters_optimize_duration",
107    // Looking at production values of the mz_optimizer_e2e_optimization_time_seconds metric, most
108    // optimizations run faster than 10ms, so this should still work well for most queries. We want
109    // to avoid the case where an optimization took just under this value and there are lots of
110    // clusters, so the extra delay to produce the plan insights notice will take the optimization
111    // time * the number of clusters longer.
112    Duration::from_millis(10),
113    "Enable plan insights fast path clusters calculation if the optimize step took less than this duration.",
114);
115
116/// Whether to use an expression cache on boot.
117pub const ENABLE_EXPRESSION_CACHE: Config<bool> = Config::new(
118    "enable_expression_cache",
119    true,
120    "Use a cache to store optimized expressions to help speed up start times.",
121);
122
123/// Whether to enable password authentication.
124pub const ENABLE_PASSWORD_AUTH: Config<bool> = Config::new(
125    "enable_password_auth",
126    false,
127    "Enable password authentication.",
128);
129
130/// Upper bound on the number of transitive dependencies validated for a
131/// read-then-write statement (e.g. `DELETE ... WHERE ... IN (SELECT ...)`).
132/// Validation walks the read set's dependency graph, which is user controlled
133/// and can be arbitrarily large. The bound rejects pathological graphs with a
134/// clean error instead of consuming unbounded time and memory.
135pub const READ_THEN_WRITE_MAX_DEPENDENCIES: Config<usize> = Config::new(
136    "read_then_write_max_dependencies",
137    100_000,
138    "Maximum number of transitive dependencies validated for a read-then-write \
139     statement before it is rejected.",
140);
141
142/// OIDC issuer URL.
143pub const OIDC_ISSUER: Config<Option<&'static str>> =
144    Config::new("oidc_issuer", None, "OIDC issuer URL.");
145
146/// OIDC audience (client IDs). When empty, audience validation is skipped.
147/// Validates that the JWT's `aud` claim contains at least one of these values.
148/// It is insecure to skip validation because it is the only
149/// mechanism preventing attackers from authenticating using a JWT
150/// issued by a dummy application, but from the same identity provider.
151pub const OIDC_AUDIENCE: Config<fn() -> serde_json::Value> = Config::new(
152    "oidc_audience",
153    || serde_json::json!([]),
154    "OIDC audience (client IDs). A JSON array of strings. When empty, audience validation is skipped.",
155);
156
157/// OIDC authentication claim to use as username
158pub const OIDC_AUTHENTICATION_CLAIM: Config<&'static str> = Config::new(
159    "oidc_authentication_claim",
160    "sub",
161    "OIDC authentication claim to use as username.",
162);
163
164/// Whether OIDC group-to-role sync is enabled.
165/// When true, JWT group claims are used to sync role memberships on login.
166pub const OIDC_GROUP_ROLE_SYNC_ENABLED: Config<bool> = Config::new(
167    "oidc_group_role_sync_enabled",
168    false,
169    "Enable OIDC JWT group-to-role membership sync on login.",
170);
171
172/// The JWT claim path that contains group memberships. May be a bare claim
173/// name (e.g. `groups`) or a dot-separated path into nested objects (e.g.
174/// `customClaims.groups`).
175pub const OIDC_GROUP_CLAIM: Config<&'static str> = Config::new(
176    "oidc_group_claim",
177    "groups",
178    "JWT claim path containing group memberships for role sync. Supports dot-separated paths into nested objects (e.g. customClaims.groups).",
179);
180
181/// Whether to reject login when group sync fails (strict/fail-closed mode).
182/// When false (default), sync failures are logged but login proceeds (fail-open).
183pub const OIDC_GROUP_ROLE_SYNC_STRICT: Config<bool> = Config::new(
184    "oidc_group_role_sync_strict",
185    false,
186    "When true, reject login if OIDC group-to-role sync fails (fail-closed).",
187);
188
189pub const PERSIST_FAST_PATH_ORDER: Config<bool> = Config::new(
190    "persist_fast_path_order",
191    false,
192    "If set, send queries with a compatible literal constraint or ordering clause down the Persist fast path.",
193);
194
195/// Whether to enforce that S3 Tables connections are in the same region as the Materialize
196/// environment.
197pub const ENABLE_S3_TABLES_REGION_CHECK: Config<bool> = Config::new(
198    "enable_s3_tables_region_check",
199    false,
200    "Whether to enforce that S3 Tables connections are in the same region as the environment.",
201);
202
203/// Whether the MCP agent endpoint is enabled.
204pub const ENABLE_MCP_AGENT: Config<bool> = Config::new(
205    "enable_mcp_agent",
206    true,
207    "Whether the MCP agent HTTP endpoint is enabled. When false, requests to /api/mcp/agent return 503 Service Unavailable.",
208);
209
210/// Whether the MCP agent query tool is enabled.
211/// When false, the `query` tool is hidden from tools/list and calls to it return an error.
212/// Agents can still use `get_data_products` and `get_data_product_details`.
213pub const ENABLE_MCP_AGENT_QUERY_TOOL: Config<bool> = Config::new(
214    "enable_mcp_agent_query_tool",
215    true,
216    "Whether the MCP agent query tool is enabled. When false, the query tool is not advertised and calls to it are rejected. Agents can still discover and inspect data products.",
217);
218
219/// Whether the MCP agent read_data_product tool is enabled.
220/// When false, the `read_data_product` tool is hidden from tools/list and calls to it return an error.
221/// The `query` tool is the general-purpose alternative for reading data products.
222pub const ENABLE_MCP_AGENT_READ_DATA_PRODUCT_TOOL: Config<bool> = Config::new(
223    "enable_mcp_agent_read_data_product_tool",
224    true,
225    "Whether the MCP agent read_data_product tool is enabled. When false, the read_data_product tool is not advertised and calls to it are rejected. Agents can use the query tool to read data products.",
226);
227
228/// Whether the MCP developer endpoint is enabled.
229pub const ENABLE_MCP_DEVELOPER: Config<bool> = Config::new(
230    "enable_mcp_developer",
231    true,
232    "Whether the MCP developer HTTP endpoint is enabled. When false, requests to /api/mcp/developer return 503 Service Unavailable.",
233);
234
235/// Whether the MCP developer query tool is enabled.
236/// When false, the `query` tool is hidden from tools/list and calls to it return an error.
237/// Developers can still use `query_system_catalog`.
238pub const ENABLE_MCP_DEVELOPER_QUERY_TOOL: Config<bool> = Config::new(
239    "enable_mcp_developer_query_tool",
240    true,
241    "Whether the MCP developer query tool is enabled. When false, the query tool is not advertised and calls to it are rejected. Developers can still use query_system_catalog.",
242);
243
244/// Whether the external metrics endpoint on environmentd is enabled.
245pub const ENABLE_PUBLIC_METRICS_ENDPOINT: Config<bool> = Config::new(
246    "enable_public_metrics_endpoint",
247    true,
248    "Whether the external metrics endpoint on environmentd is enabled. When false, requests return 503.",
249);
250
251/// Maximum size (in bytes) of MCP tool response content after JSON serialization.
252/// Responses exceeding this limit are rejected with a clear error telling the
253/// agent to narrow its query. Keeps responses within LLM context window limits.
254pub const MCP_MAX_RESPONSE_SIZE: Config<usize> = Config::new(
255    "mcp_max_response_size",
256    1_000_000,
257    "Maximum size in bytes of MCP tool response content. Responses exceeding this limit are rejected with an error telling the agent to narrow its query.",
258);
259
260/// Maximum time an MCP request may run before it is aborted and a timeout
261/// error is returned to the client.
262pub const MCP_REQUEST_TIMEOUT: Config<Duration> = Config::new(
263    "mcp_request_timeout",
264    Duration::from_secs(60),
265    "Maximum time an MCP request may run before it is aborted with a timeout error.",
266);
267
268/// Maximum size (in bytes) of a webhook request body, measured after
269/// decompression. Requests whose body exceeds this limit are rejected with
270/// HTTP 413. Applies only to the webhook route; other HTTP routes use a
271/// separate static limit.
272pub const WEBHOOK_MAX_REQUEST_SIZE_BYTES: Config<usize> = Config::new(
273    "webhook_max_request_size_bytes",
274    // Matches `MAX_REQUEST_SIZE`, the static limit the other environmentd HTTP routes use.
275    5 * 1024 * 1024,
276    "The maximum size in bytes of a webhook request body, measured after decompression.",
277);
278
279/// Number of user IDs to pre-allocate in a batch. Pre-allocating IDs avoids
280/// a persist write + oracle call per DDL statement.
281pub const USER_ID_POOL_BATCH_SIZE: Config<u32> = Config::new(
282    "user_id_pool_batch_size",
283    512,
284    "Number of user IDs to pre-allocate in a batch for DDL operations.",
285);
286
287/// Maximum number of txns-shard write attempts before rebuilding `environmentd`.
288///
289/// The effective minimum is one attempt.
290pub const GROUP_COMMIT_MAX_ATTEMPTS: Config<usize> = Config::new(
291    "group_commit_max_attempts",
292    100,
293    "Maximum number of txns-shard write attempts before rebuilding environmentd. Values below 1 are treated as 1.",
294);
295
296/// OIDC client ID for the web console.
297pub const CONSOLE_OIDC_CLIENT_ID: Config<&'static str> = Config::new(
298    "console_oidc_client_id",
299    "",
300    "OIDC client ID for the web console.",
301);
302
303/// Space-separated OIDC scopes requested by the web console.
304pub const CONSOLE_OIDC_SCOPES: Config<&'static str> = Config::new(
305    "console_oidc_scopes",
306    "",
307    "Space-separated OIDC scopes requested by the web console.",
308);
309
310/// Interval at which to collect per-object arrangement size snapshots for the history table.
311pub const ARRANGEMENT_SIZE_HISTORY_COLLECTION_INTERVAL: Config<Duration> = Config::new(
312    "arrangement_size_history_collection_interval",
313    // Disabled by default until https://github.com/MaterializeInc/materialize/pull/37455 lands.
314    Duration::ZERO,
315    "Interval at which to collect and snapshot per-object arrangement sizes \
316     into mz_internal.mz_object_arrangement_size_history.",
317);
318
319/// How long to retain per-object arrangement size history.
320pub const ARRANGEMENT_SIZE_HISTORY_RETENTION_PERIOD: Config<Duration> = Config::new(
321    "arrangement_size_history_retention_period",
322    Duration::from_hours(7 * 24),
323    "How long to retain rows in mz_internal.mz_object_arrangement_size_history.",
324);
325
326/// How frequently the catalog `*_info` metrics (`mz_object_info`,
327/// `mz_cluster_info`, …) are reconciled with the catalog. A zero duration
328/// disables reconciliation.
329pub const CATALOG_INFO_METRICS_RECONCILE_INTERVAL: Config<Duration> = Config::new(
330    "catalog_info_metrics_reconcile_interval",
331    Duration::from_secs(30),
332    "How frequently to reconcile the catalog `*_info` metrics with the catalog. A zero duration disables reconciliation.",
333);
334
335/// Server-side `statement_timeout` to set on Postgres/CRDB connections used by
336/// the Postgres/CRDB timestamp oracle. A zero value leaves the statement
337/// timeout unset.
338pub const PG_TIMESTAMP_ORACLE_STATEMENT_TIMEOUT: Config<Duration> = Config::new(
339    "pg_timestamp_oracle_statement_timeout",
340    crate::timestamp_oracle::DEFAULT_PG_TIMESTAMP_ORACLE_STATEMENT_TIMEOUT,
341    "The server-side statement timeout to set on Postgres/CRDB connections used by the \
342    Postgres/CRDB timestamp oracle. A value of zero leaves the statement timeout unset.",
343);
344
345/// Whether per-cluster and per-replica scoped system parameters are evaluated.
346/// Off by default: the parameter sync loop evaluates no cluster/replica
347/// contexts and resolution falls back to the environment-wide value everywhere
348/// (the pre-scoped behavior). Enabling it (e.g. from LaunchDarkly) turns on
349/// scoped evaluation without a deploy.
350pub const ENABLE_SCOPED_SYSTEM_PARAMETERS: Config<bool> = Config::new(
351    "enable_scoped_system_parameters",
352    false,
353    "Whether per-cluster and per-replica scoped system parameters are evaluated and applied.",
354);
355
356/// Top-level gate for the cluster controller. When on, the controller owns the
357/// managed-cluster replica set and the legacy paths (the graceful 3-stage
358/// machine and `cluster_scheduling.rs`) are bypassed. The replica set cannot
359/// have two writers, so this is a clean switch, not a per-strategy toggle.
360///
361/// Defaults on. This is the break-glass switch to fall back to the legacy
362/// paths if the controller misbehaves.
363pub const ENABLE_CLUSTER_CONTROLLER: Config<bool> = Config::new(
364    "enable_cluster_controller",
365    true,
366    "Whether the cluster controller owns the managed-cluster replica set. When false, the legacy scheduling and graceful-reconfiguration paths run instead.",
367);
368
369/// Cadence of the cluster controller's reconcile tick.
370///
371/// Replaces `cluster_check_scheduling_policies_interval` once the controller is
372/// the sole owner; while the controller is dark both intervals exist.
373pub const CLUSTER_CONTROLLER_TICK_INTERVAL: Config<Duration> = Config::new(
374    "cluster_controller_tick_interval",
375    Duration::from_secs(5),
376    "How often the cluster controller runs a reconcile tick.",
377);
378
379/// Whether a config-shape `ALTER CLUSTER` returns immediately, with the
380/// controller converging in the background, or blocks the session on a
381/// wait-shim until the reconfiguration completes or its deadline passes.
382///
383/// Only consulted while [`ENABLE_CLUSTER_CONTROLLER`] is on, when the
384/// controller owns the reconfiguration.
385///
386/// Defaults on. This is the break-glass switch back to the blocking wait-shim
387/// if returning immediately causes trouble.
388pub const ENABLE_BACKGROUND_ALTER_CLUSTER: Config<bool> = Config::new(
389    "enable_background_alter_cluster",
390    true,
391    "Whether a config-shape ALTER CLUSTER returns immediately (true) or the session blocks on a wait-shim over the durable reconfiguration record (false).",
392);
393
394/// The reconfiguration deadline written when a config-shape `ALTER CLUSTER`
395/// omits `WITH (WAIT ...)`. What happens when the deadline passes un-hydrated is
396/// the record's `on_timeout` action.
397pub const DEFAULT_CLUSTER_RECONFIGURATION_TIMEOUT: Config<Duration> = Config::new(
398    "default_cluster_reconfiguration_timeout",
399    Duration::from_secs(60 * 60 * 24),
400    "The reconfiguration deadline written when a config-shape ALTER CLUSTER omits WITH (WAIT ...).",
401);
402
403/// Break-glass for the hydration-burst strategy: when off the controller never
404/// runs a burst replica; graceful reconfiguration and `ON REFRESH` scheduling
405/// are unaffected.
406///
407/// Only consulted while [`ENABLE_CLUSTER_CONTROLLER`] is on. A cluster can only
408/// carry an `AUTO SCALING STRATEGY` while its SQL acceptance feature flag is
409/// on, so this is the second of the two gates burst sits behind.
410pub const ENABLE_HYDRATION_BURST: Config<bool> = Config::new(
411    "enable_hydration_burst",
412    true,
413    "Whether the cluster controller's hydration-burst strategy may run a burst replica (break-glass; leaves graceful reconfiguration and ON REFRESH untouched).",
414);
415
416/// The burst-replica linger duration written into a new `burst` record when the
417/// cluster's `AUTO SCALING STRATEGY` omits `LINGER DURATION`. The burst replica
418/// stays up this long after the steady-state replicas first hydrate.
419pub const DEFAULT_HYDRATION_BURST_LINGER: Config<Duration> = Config::new(
420    "default_hydration_burst_linger",
421    Duration::from_secs(0),
422    "The burst-replica linger duration written when an AUTO SCALING STRATEGY omits LINGER DURATION.",
423);
424
425/// Adds the full set of all adapter `Config`s.
426pub fn all_dyncfgs(configs: ConfigSet) -> ConfigSet {
427    configs
428        .add(&ALLOW_USER_SESSIONS)
429        .add(&ENABLE_CLUSTER_CONTROLLER)
430        .add(&CLUSTER_CONTROLLER_TICK_INTERVAL)
431        .add(&ENABLE_BACKGROUND_ALTER_CLUSTER)
432        .add(&DEFAULT_CLUSTER_RECONFIGURATION_TIMEOUT)
433        .add(&ENABLE_HYDRATION_BURST)
434        .add(&DEFAULT_HYDRATION_BURST_LINGER)
435        .add(&WITH_0DT_DEPLOYMENT_MAX_WAIT)
436        .add(&WITH_0DT_DEPLOYMENT_DDL_CHECK_INTERVAL)
437        .add(&ENABLE_0DT_DEPLOYMENT_PANIC_AFTER_TIMEOUT)
438        .add(&WITH_0DT_DEPLOYMENT_CAUGHT_UP_CHECK_INTERVAL)
439        .add(&WITH_0DT_CAUGHT_UP_CHECK_ALLOWED_LAG)
440        .add(&WITH_0DT_CAUGHT_UP_CHECK_CUTOFF)
441        .add(&ENABLE_0DT_CAUGHT_UP_REPLICA_STATUS_CHECK)
442        .add(&ENABLE_0DT_CAUGHT_UP_STABILITY_CHECK)
443        .add(&WITH_0DT_CAUGHT_UP_CHECK_STABILITY_PERIOD)
444        .add(&ENABLE_STATEMENT_LIFECYCLE_LOGGING)
445        .add(&ENABLE_INTROSPECTION_SUBSCRIBES)
446        .add(&ENABLE_FRONTEND_SUBSCRIBES)
447        .add(&PLAN_INSIGHTS_NOTICE_FAST_PATH_CLUSTERS_OPTIMIZE_DURATION)
448        .add(&ENABLE_EXPRESSION_CACHE)
449        .add(&ENABLE_PASSWORD_AUTH)
450        .add(&READ_THEN_WRITE_MAX_DEPENDENCIES)
451        .add(&OIDC_ISSUER)
452        .add(&OIDC_AUDIENCE)
453        .add(&OIDC_AUTHENTICATION_CLAIM)
454        .add(&OIDC_GROUP_ROLE_SYNC_ENABLED)
455        .add(&OIDC_GROUP_CLAIM)
456        .add(&OIDC_GROUP_ROLE_SYNC_STRICT)
457        .add(&PERSIST_FAST_PATH_ORDER)
458        .add(&ENABLE_S3_TABLES_REGION_CHECK)
459        .add(&ENABLE_MCP_AGENT)
460        .add(&ENABLE_MCP_AGENT_QUERY_TOOL)
461        .add(&ENABLE_MCP_AGENT_READ_DATA_PRODUCT_TOOL)
462        .add(&ENABLE_MCP_DEVELOPER)
463        .add(&ENABLE_MCP_DEVELOPER_QUERY_TOOL)
464        .add(&ENABLE_PUBLIC_METRICS_ENDPOINT)
465        .add(&MCP_MAX_RESPONSE_SIZE)
466        .add(&MCP_REQUEST_TIMEOUT)
467        .add(&WEBHOOK_MAX_REQUEST_SIZE_BYTES)
468        .add(&USER_ID_POOL_BATCH_SIZE)
469        .add(&GROUP_COMMIT_MAX_ATTEMPTS)
470        .add(&CONSOLE_OIDC_CLIENT_ID)
471        .add(&CONSOLE_OIDC_SCOPES)
472        .add(&ARRANGEMENT_SIZE_HISTORY_COLLECTION_INTERVAL)
473        .add(&ARRANGEMENT_SIZE_HISTORY_RETENTION_PERIOD)
474        .add(&CATALOG_INFO_METRICS_RECONCILE_INTERVAL)
475        .add(&PG_TIMESTAMP_ORACLE_STATEMENT_TIMEOUT)
476        .add(&ENABLE_SCOPED_SYSTEM_PARAMETERS)
477}