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    Duration::from_secs(60 * 60 * 72),
26    "How long to wait at most for clusters to be hydrated, when doing a zero-downtime deployment.",
27);
28
29pub const WITH_0DT_DEPLOYMENT_DDL_CHECK_INTERVAL: Config<Duration> = Config::new(
30    "with_0dt_deployment_ddl_check_interval",
31    Duration::from_secs(5 * 60),
32    "How often to check for DDL changes during zero-downtime deployment.",
33);
34
35pub const ENABLE_0DT_DEPLOYMENT_PANIC_AFTER_TIMEOUT: Config<bool> = Config::new(
36    "enable_0dt_deployment_panic_after_timeout",
37    false,
38    "Whether to panic if the maximum wait time is reached but preflight checks have not succeeded.",
39);
40
41pub const WITH_0DT_DEPLOYMENT_CAUGHT_UP_CHECK_INTERVAL: Config<Duration> = Config::new(
42    // The feature flag name is historical.
43    "0dt_deployment_hydration_check_interval",
44    Duration::from_secs(10),
45    "Interval at which to check whether clusters are caught up, when doing zero-downtime deployment.",
46);
47
48pub const WITH_0DT_CAUGHT_UP_CHECK_ALLOWED_LAG: Config<Duration> = Config::new(
49    "with_0dt_caught_up_check_allowed_lag",
50    Duration::from_secs(60),
51    "Maximum allowed lag when determining whether collections are caught up for 0dt deployments.",
52);
53
54pub const WITH_0DT_CAUGHT_UP_CHECK_CUTOFF: Config<Duration> = Config::new(
55    "with_0dt_caught_up_check_cutoff",
56    Duration::from_secs(2 * 60 * 60), // 2 hours
57    "Collections whose write frontier is behind 'now' by more than the cutoff are ignored when doing caught-up checks for 0dt deployments.",
58);
59
60pub const ENABLE_0DT_CAUGHT_UP_REPLICA_STATUS_CHECK: Config<bool> = Config::new(
61    "enable_0dt_caught_up_replica_status_check",
62    true,
63    "Enable checking for crash/OOM-looping replicas during 0dt caught-up checks. Emergency break-glass flag to disable this feature if needed.",
64);
65
66/// Enable logging of statement lifecycle events in mz_internal.mz_statement_lifecycle_history.
67pub const ENABLE_STATEMENT_LIFECYCLE_LOGGING: Config<bool> = Config::new(
68    "enable_statement_lifecycle_logging",
69    true,
70    "Enable logging of statement lifecycle events in mz_internal.mz_statement_lifecycle_history.",
71);
72
73/// Enable installation of introspection subscribes.
74pub const ENABLE_INTROSPECTION_SUBSCRIBES: Config<bool> = Config::new(
75    "enable_introspection_subscribes",
76    true,
77    "Enable installation of introspection subscribes.",
78);
79
80/// Enable sending subscribes down the new frontend-peek path.
81pub const ENABLE_FRONTEND_SUBSCRIBES: Config<bool> = Config::new(
82    "enable_frontend_subscribes",
83    true,
84    "Enable sending subscribes down the new frontend-peek path.",
85);
86
87/// The plan insights notice will not investigate fast path clusters if plan optimization took longer than this.
88pub const PLAN_INSIGHTS_NOTICE_FAST_PATH_CLUSTERS_OPTIMIZE_DURATION: Config<Duration> = Config::new(
89    "plan_insights_notice_fast_path_clusters_optimize_duration",
90    // Looking at production values of the mz_optimizer_e2e_optimization_time_seconds metric, most
91    // optimizations run faster than 10ms, so this should still work well for most queries. We want
92    // to avoid the case where an optimization took just under this value and there are lots of
93    // clusters, so the extra delay to produce the plan insights notice will take the optimization
94    // time * the number of clusters longer.
95    Duration::from_millis(10),
96    "Enable plan insights fast path clusters calculation if the optimize step took less than this duration.",
97);
98
99/// Whether to use an expression cache on boot.
100pub const ENABLE_EXPRESSION_CACHE: Config<bool> = Config::new(
101    "enable_expression_cache",
102    true,
103    "Use a cache to store optimized expressions to help speed up start times.",
104);
105
106/// Whether to enable password authentication.
107pub const ENABLE_PASSWORD_AUTH: Config<bool> = Config::new(
108    "enable_password_auth",
109    false,
110    "Enable password authentication.",
111);
112
113/// OIDC issuer URL.
114pub const OIDC_ISSUER: Config<Option<&'static str>> =
115    Config::new("oidc_issuer", None, "OIDC issuer URL.");
116
117/// OIDC audience (client IDs). When empty, audience validation is skipped.
118/// Validates that the JWT's `aud` claim contains at least one of these values.
119/// It is insecure to skip validation because it is the only
120/// mechanism preventing attackers from authenticating using a JWT
121/// issued by a dummy application, but from the same identity provider.
122pub const OIDC_AUDIENCE: Config<fn() -> serde_json::Value> = Config::new(
123    "oidc_audience",
124    || serde_json::json!([]),
125    "OIDC audience (client IDs). A JSON array of strings. When empty, audience validation is skipped.",
126);
127
128/// OIDC authentication claim to use as username
129pub const OIDC_AUTHENTICATION_CLAIM: Config<&'static str> = Config::new(
130    "oidc_authentication_claim",
131    "sub",
132    "OIDC authentication claim to use as username.",
133);
134
135/// Whether OIDC group-to-role sync is enabled.
136/// When true, JWT group claims are used to sync role memberships on login.
137pub const OIDC_GROUP_ROLE_SYNC_ENABLED: Config<bool> = Config::new(
138    "oidc_group_role_sync_enabled",
139    false,
140    "Enable OIDC JWT group-to-role membership sync on login.",
141);
142
143/// The JWT claim name that contains group memberships.
144pub const OIDC_GROUP_CLAIM: Config<&'static str> = Config::new(
145    "oidc_group_claim",
146    "groups",
147    "JWT claim name containing group memberships for role sync.",
148);
149
150/// Whether to reject login when group sync fails (strict/fail-closed mode).
151/// When false (default), sync failures are logged but login proceeds (fail-open).
152pub const OIDC_GROUP_ROLE_SYNC_STRICT: Config<bool> = Config::new(
153    "oidc_group_role_sync_strict",
154    false,
155    "When true, reject login if OIDC group-to-role sync fails (fail-closed).",
156);
157
158pub const PERSIST_FAST_PATH_ORDER: Config<bool> = Config::new(
159    "persist_fast_path_order",
160    false,
161    "If set, send queries with a compatible literal constraint or ordering clause down the Persist fast path.",
162);
163
164/// Whether to enforce that S3 Tables connections are in the same region as the Materialize
165/// environment.
166pub const ENABLE_S3_TABLES_REGION_CHECK: Config<bool> = Config::new(
167    "enable_s3_tables_region_check",
168    false,
169    "Whether to enforce that S3 Tables connections are in the same region as the environment.",
170);
171
172/// Whether the MCP agent endpoint is enabled.
173pub const ENABLE_MCP_AGENT: Config<bool> = Config::new(
174    "enable_mcp_agent",
175    true,
176    "Whether the MCP agent HTTP endpoint is enabled. When false, requests to /api/mcp/agent return 503 Service Unavailable.",
177);
178
179/// Whether the MCP agent query tool is enabled.
180/// When false, the `query` tool is hidden from tools/list and calls to it return an error.
181/// Agents can still use `get_data_products` and `get_data_product_details`.
182pub const ENABLE_MCP_AGENT_QUERY_TOOL: Config<bool> = Config::new(
183    "enable_mcp_agent_query_tool",
184    false,
185    "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.",
186);
187
188/// Whether the MCP developer endpoint is enabled.
189pub const ENABLE_MCP_DEVELOPER: Config<bool> = Config::new(
190    "enable_mcp_developer",
191    true,
192    "Whether the MCP developer HTTP endpoint is enabled. When false, requests to /api/mcp/developer return 503 Service Unavailable.",
193);
194
195/// Maximum size (in bytes) of MCP tool response content after JSON serialization.
196/// Responses exceeding this limit are rejected with a clear error telling the
197/// agent to narrow its query. Keeps responses within LLM context window limits.
198pub const MCP_MAX_RESPONSE_SIZE: Config<usize> = Config::new(
199    "mcp_max_response_size",
200    1_000_000,
201    "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.",
202);
203
204/// Number of user IDs to pre-allocate in a batch. Pre-allocating IDs avoids
205/// a persist write + oracle call per DDL statement.
206pub const USER_ID_POOL_BATCH_SIZE: Config<u32> = Config::new(
207    "user_id_pool_batch_size",
208    512,
209    "Number of user IDs to pre-allocate in a batch for DDL operations.",
210);
211
212/// OIDC client ID for the web console.
213pub const CONSOLE_OIDC_CLIENT_ID: Config<&'static str> = Config::new(
214    "console_oidc_client_id",
215    "",
216    "OIDC client ID for the web console.",
217);
218
219/// Space-separated OIDC scopes requested by the web console.
220pub const CONSOLE_OIDC_SCOPES: Config<&'static str> = Config::new(
221    "console_oidc_scopes",
222    "",
223    "Space-separated OIDC scopes requested by the web console.",
224);
225
226/// Interval at which to collect per-object arrangement size snapshots for the history table.
227pub const ARRANGEMENT_SIZE_HISTORY_COLLECTION_INTERVAL: Config<Duration> = Config::new(
228    "arrangement_size_history_collection_interval",
229    Duration::from_hours(1),
230    "Interval at which to collect and snapshot per-object arrangement sizes \
231     into mz_internal.mz_object_arrangement_size_history.",
232);
233
234/// How long to retain per-object arrangement size history.
235pub const ARRANGEMENT_SIZE_HISTORY_RETENTION_PERIOD: Config<Duration> = Config::new(
236    "arrangement_size_history_retention_period",
237    Duration::from_hours(7 * 24),
238    "How long to retain rows in mz_internal.mz_object_arrangement_size_history.",
239);
240
241/// Adds the full set of all adapter `Config`s.
242pub fn all_dyncfgs(configs: ConfigSet) -> ConfigSet {
243    configs
244        .add(&ALLOW_USER_SESSIONS)
245        .add(&WITH_0DT_DEPLOYMENT_MAX_WAIT)
246        .add(&WITH_0DT_DEPLOYMENT_DDL_CHECK_INTERVAL)
247        .add(&ENABLE_0DT_DEPLOYMENT_PANIC_AFTER_TIMEOUT)
248        .add(&WITH_0DT_DEPLOYMENT_CAUGHT_UP_CHECK_INTERVAL)
249        .add(&WITH_0DT_CAUGHT_UP_CHECK_ALLOWED_LAG)
250        .add(&WITH_0DT_CAUGHT_UP_CHECK_CUTOFF)
251        .add(&ENABLE_0DT_CAUGHT_UP_REPLICA_STATUS_CHECK)
252        .add(&ENABLE_STATEMENT_LIFECYCLE_LOGGING)
253        .add(&ENABLE_INTROSPECTION_SUBSCRIBES)
254        .add(&ENABLE_FRONTEND_SUBSCRIBES)
255        .add(&PLAN_INSIGHTS_NOTICE_FAST_PATH_CLUSTERS_OPTIMIZE_DURATION)
256        .add(&ENABLE_EXPRESSION_CACHE)
257        .add(&ENABLE_PASSWORD_AUTH)
258        .add(&OIDC_ISSUER)
259        .add(&OIDC_AUDIENCE)
260        .add(&OIDC_AUTHENTICATION_CLAIM)
261        .add(&OIDC_GROUP_ROLE_SYNC_ENABLED)
262        .add(&OIDC_GROUP_CLAIM)
263        .add(&OIDC_GROUP_ROLE_SYNC_STRICT)
264        .add(&PERSIST_FAST_PATH_ORDER)
265        .add(&ENABLE_S3_TABLES_REGION_CHECK)
266        .add(&ENABLE_MCP_AGENT)
267        .add(&ENABLE_MCP_AGENT_QUERY_TOOL)
268        .add(&ENABLE_MCP_DEVELOPER)
269        .add(&MCP_MAX_RESPONSE_SIZE)
270        .add(&USER_ID_POOL_BATCH_SIZE)
271        .add(&CONSOLE_OIDC_CLIENT_ID)
272        .add(&CONSOLE_OIDC_SCOPES)
273        .add(&ARRANGEMENT_SIZE_HISTORY_COLLECTION_INTERVAL)
274        .add(&ARRANGEMENT_SIZE_HISTORY_RETENTION_PERIOD)
275}