diff --git a/.sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json b/.sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json index e3b4b38a4..03c79bcb7 100644 --- a/.sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json +++ b/.sqlx/query-078285805ae4812c5c5bc57b4f748840cee8e29186fc476e2ef148688385c6a4.json @@ -14,7 +14,7 @@ "Text", "Text", "Int4", - "Int4", + "Int8", "InetArray", "Timestamp", "Bool", diff --git a/.sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json b/.sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json index 2fe8994fa..3ee27a31e 100644 --- a/.sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json +++ b/.sqlx/query-0e2e17c49ac83e9b8b70c8bcadc8bfbed999267ca3ced60f27f1e3c08b2e9574.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -128,8 +128,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json b/.sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json index af158e1d7..b14175e6e 100644 --- a/.sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json +++ b/.sqlx/query-28a9206e4aef6a3d61e8712164419429e4fc7c1fee0da935845977634d730bec.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -130,8 +130,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json b/.sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json index 73696fca2..ac2739265 100644 --- a/.sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json +++ b/.sqlx/query-68f067597d1577f4bc05dae41b78ae792fab1b5c4e9e9e7269449aee64c24bf8.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -128,8 +128,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json b/.sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json index 8cc1a71b7..58dff1139 100644 --- a/.sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json +++ b/.sqlx/query-6e832a038605f8c13f0cf4f0cd215fa8db7959af23c59766e2a9e4af5233b726.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -130,8 +130,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json b/.sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json index 9f1e3c90a..321e92ec7 100644 --- a/.sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json +++ b/.sqlx/query-785629b8de2268c1311fe27a5727e3e416d4e6d1a5f5097d92b1bd8ec446deb1.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -130,8 +130,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json b/.sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json index 91c334b94..648db1840 100644 --- a/.sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json +++ b/.sqlx/query-90cf3926dd7449fd8cd164871c63919b74f05a8797db690ccb3b5a8534415cfb.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -130,8 +130,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json b/.sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json index 68a22565e..42e1a761c 100644 --- a/.sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json +++ b/.sqlx/query-cd6a0b78b618518ac4c1b644c3d1bd3ffabd5ad1ed9a260ca3a821c9a187b7d3.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -130,8 +130,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/.sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json b/.sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json index a682508ee..d93ff4d99 100644 --- a/.sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json +++ b/.sqlx/query-ddcf4b1bff7758d8ccd0ee7af140448b94154dabc60a5ea12dfd16e1920cf52b.json @@ -19,7 +19,7 @@ "Text", "Text", "Int4", - "Int4", + "Int8", "InetArray", "Timestamp", "Bool", diff --git a/.sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json b/.sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json index 9afc26714..c4ae7b9d3 100644 --- a/.sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json +++ b/.sqlx/query-e8d80473ffc42c6febc3e81ca9c7e9b1b7f5040b0dfb3d31f60d2bcbdc06dfae.json @@ -51,7 +51,7 @@ { "ordinal": 9, "name": "fwmark", - "type_info": "Int4" + "type_info": "Int8" }, { "ordinal": 10, @@ -128,8 +128,8 @@ false, false, true, - true, - true, + false, + false, false, true, false, diff --git a/Cargo.lock b/Cargo.lock index f2f43eb59..4bab99587 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -596,9 +596,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.53" +version = "1.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "755d2fce177175ffca841e9a06afdb2c4ab0f593d53b4dee48147dfaade85932" +checksum = "6354c81bbfd62d9cfa9cb3c773c2b7b2a3a482d569de977fd0e961f6e7c00583" dependencies = [ "find-msvc-tools", "jobserver", @@ -4018,9 +4018,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.105" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535d180e0ecab6268a3e718bb9fd44db66bbbc256257165fc699dadf70d16fe7" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -4189,9 +4189,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc74d9a594b72ae6656596548f56f667211f8a97b3d4c3d467150794690dc40a" +checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" dependencies = [ "proc-macro2", ] diff --git a/crates/defguard_common/src/config.rs b/crates/defguard_common/src/config.rs index cfd209b22..1d74044bd 100644 --- a/crates/defguard_common/src/config.rs +++ b/crates/defguard_common/src/config.rs @@ -207,9 +207,9 @@ pub struct InitVpnLocationArgs { #[arg(long)] pub dns: Option, #[arg(long)] - pub mtu: Option, + pub mtu: u32, #[arg(long)] - pub fwmark: Option, + pub fwmark: u32, #[arg(long)] pub allowed_ips: Vec, #[arg(long)] diff --git a/crates/defguard_common/src/db/models/wireguard.rs b/crates/defguard_common/src/db/models/wireguard.rs index 0355c4d40..6dddd4b16 100644 --- a/crates/defguard_common/src/db/models/wireguard.rs +++ b/crates/defguard_common/src/db/models/wireguard.rs @@ -41,6 +41,8 @@ use crate::{ pub const DEFAULT_KEEPALIVE_INTERVAL: i32 = 25; pub const DEFAULT_DISCONNECT_THRESHOLD: i32 = 300; +/// Default MTU for WireGuard interfaces. +pub const DEFAULT_WIREGUARD_MTU: i32 = 1420; // TODO: change to u32 once sqlx unsigned integers. // Used in process of importing network from WireGuard config. #[derive(Clone, Debug, Deserialize, Serialize)] @@ -115,8 +117,8 @@ pub struct WireguardNetwork { pub prvkey: String, pub endpoint: String, pub dns: Option, - pub mtu: Option, // Should be Option, but sqlx won't allow that. - pub fwmark: Option, // Should be Option, but sqlx won't allow that. + pub mtu: i32, // Should be u32, but sqlx won't allow that. + pub fwmark: i64, // Should be u32, but sqlx won't allow that. #[model(ref)] #[schema(value_type = String)] pub allowed_ips: Vec, @@ -220,8 +222,8 @@ impl WireguardNetwork { port: i32, endpoint: String, dns: Option, - mtu: Option, - fwmark: Option, + mtu: i32, + fwmark: i64, allowed_ips: Vec, keepalive_interval: i32, peer_disconnect_threshold: i32, @@ -337,13 +339,14 @@ impl WireguardNetwork { transaction: &mut PgConnection, ) -> Result>, ModelError> { debug!("Fetching all allowed devices for network {}", self); - let devices = match self.get_allowed_groups(&mut *transaction).await? { - // devices need to be filtered by allowed group - Some(allowed_groups) => { - query_as!( + let devices = + match self.get_allowed_groups(&mut *transaction).await? { + // devices need to be filtered by allowed group + Some(allowed_groups) => { + query_as!( Device, - "SELECT DISTINCT ON (d.id) d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, d.description, d.device_type \"device_type: DeviceType\", \ - configured + "SELECT DISTINCT ON (d.id) d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, \ + d.description, d.device_type \"device_type: DeviceType\", configured FROM device d \ JOIN \"user\" u ON d.user_id = u.id \ JOIN group_user gu ON u.id = gu.user_id \ @@ -354,15 +357,14 @@ impl WireguardNetwork { ORDER BY d.id ASC", &allowed_groups ) - .fetch_all(&mut *transaction) - .await? - } - // all devices of enabled users are allowed - None => { - query_as!( + .fetch_all(&mut *transaction) + .await? + } + // all devices of enabled users are allowed + None => query_as!( Device, - "SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, d.description, d.device_type \"device_type: DeviceType\", \ - configured \ + "SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, d.description, \ + d.device_type \"device_type: DeviceType\", configured \ FROM device d \ JOIN \"user\" u ON d.user_id = u.id \ WHERE u.is_active = true \ @@ -370,9 +372,8 @@ impl WireguardNetwork { ORDER BY d.id ASC" ) .fetch_all(&mut *transaction) - .await? - } - }; + .await?, + }; Ok(devices) } @@ -385,13 +386,14 @@ impl WireguardNetwork { user_id: Id, ) -> Result>, ModelError> { debug!("Fetching all allowed devices for network {self}, user ID {user_id}"); - let devices = match self.get_allowed_groups(&mut *transaction).await? { - // devices need to be filtered by allowed group - Some(allowed_groups) => { - query_as!( + let devices = + match self.get_allowed_groups(&mut *transaction).await? { + // devices need to be filtered by allowed group + Some(allowed_groups) => { + query_as!( Device, - "SELECT DISTINCT ON (d.id) d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, d.description, d.device_type \"device_type: DeviceType\", \ - configured + "SELECT DISTINCT ON (d.id) d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, \ + d.description, d.device_type \"device_type: DeviceType\", configured FROM device d \ JOIN \"user\" u ON d.user_id = u.id \ JOIN group_user gu ON u.id = gu.user_id \ @@ -403,26 +405,25 @@ impl WireguardNetwork { ORDER BY d.id ASC", &allowed_groups, user_id ) - .fetch_all(&mut *transaction) - .await? - } - // all devices of enabled users are allowed - None => { - query_as!( + .fetch_all(&mut *transaction) + .await? + } + // all devices of enabled users are allowed + None => query_as!( Device, - "SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, d.description, d.device_type \"device_type: DeviceType\", \ - configured \ + "SELECT d.id, d.name, d.wireguard_pubkey, d.user_id, d.created, d.description, \ + d.device_type \"device_type: DeviceType\", configured \ FROM device d \ JOIN \"user\" u ON d.user_id = u.id \ WHERE u.is_active = true \ AND d.device_type = 'user'::device_type \ AND d.user_id = $1 \ - ORDER BY d.id ASC", user_id + ORDER BY d.id ASC", + user_id ) .fetch_all(&mut *transaction) - .await? - } - }; + .await?, + }; Ok(devices) } @@ -1018,7 +1019,8 @@ impl WireguardNetwork { query_as!( VpnClientSession, "SELECT id, location_id, user_id, device_id, \ - created_at, connected_at, disconnected_at, mfa_mode \"mfa_mode: LocationMfaMode\", state \"state: VpnClientSessionState\" \ + created_at, connected_at, disconnected_at, mfa_mode \"mfa_mode: LocationMfaMode\", \ + state \"state: VpnClientSessionState\" \ FROM vpn_client_session \ WHERE location_id = $1 AND state = 'connected'::vpn_client_session_state", self.id, @@ -1040,8 +1042,8 @@ impl Default for WireguardNetwork { prvkey: String::default(), endpoint: String::default(), dns: Option::default(), - mtu: Option::default(), - fwmark: Option::default(), + mtu: DEFAULT_WIREGUARD_MTU, + fwmark: 0, allowed_ips: Vec::default(), connected_at: Option::default(), keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, @@ -1497,8 +1499,8 @@ mod test { 50051, String::new(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, vec![IpNetwork::from_str("10.1.1.0/24").unwrap()], 300, 300, @@ -1631,8 +1633,8 @@ mod test { 50051, String::new(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, vec![IpNetwork::from_str("10.1.1.0/24").unwrap()], 300, 300, diff --git a/crates/defguard_core/src/enterprise/db/models/acl/tests.rs b/crates/defguard_core/src/enterprise/db/models/acl/tests.rs index 1531135cd..9a0f5c96f 100644 --- a/crates/defguard_core/src/enterprise/db/models/acl/tests.rs +++ b/crates/defguard_core/src/enterprise/db/models/acl/tests.rs @@ -1,6 +1,9 @@ use std::ops::Bound; -use defguard_common::{db::setup_pool, utils::parse_address_list}; +use defguard_common::{ + db::{models::wireguard::DEFAULT_WIREGUARD_MTU, setup_pool}, + utils::parse_address_list, +}; use rand::{Rng, thread_rng}; use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; @@ -176,8 +179,8 @@ async fn test_rule_relations(_: PgPoolOptions, options: PgConnectOptions) { 1000, "endpoint1".to_string(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, Vec::new(), 100, 100, @@ -195,8 +198,8 @@ async fn test_rule_relations(_: PgPoolOptions, options: PgConnectOptions) { 2000, "endpoint2".to_string(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, Vec::new(), 200, 200, diff --git a/crates/defguard_core/src/enterprise/directory_sync/tests.rs b/crates/defguard_core/src/enterprise/directory_sync/tests.rs index c3e607924..671a58e3c 100644 --- a/crates/defguard_core/src/enterprise/directory_sync/tests.rs +++ b/crates/defguard_core/src/enterprise/directory_sync/tests.rs @@ -52,8 +52,8 @@ mod test { 1234, "123.123.123.123".to_string(), None, - None, - None, + 1420, + 0, Vec::new(), 32, 32, diff --git a/crates/defguard_core/src/grpc/gateway/mod.rs b/crates/defguard_core/src/grpc/gateway/mod.rs index a482a2519..60bfc863a 100644 --- a/crates/defguard_core/src/grpc/gateway/mod.rs +++ b/crates/defguard_core/src/grpc/gateway/mod.rs @@ -9,7 +9,11 @@ use chrono::DateTime; use defguard_common::{ db::{ ChangeNotification, Id, TriggerOperation, - models::{WireguardNetwork, gateway::Gateway, wireguard::ServiceLocationMode}, + models::{ + WireguardNetwork, + gateway::Gateway, + wireguard::{DEFAULT_WIREGUARD_MTU, ServiceLocationMode}, + }, }, messages::peer_stats_update::PeerStatsUpdate, }; @@ -239,8 +243,8 @@ fn gen_config( addresses: network.address.iter().map(ToString::to_string).collect(), peers, firewall_config: maybe_firewall_config, - mtu: network.mtu.map(|i| i as u32), - fwmark: network.fwmark.map(|i| i as u32), + mtu: network.mtu as u32, + fwmark: network.fwmark as u32, } } @@ -549,8 +553,8 @@ impl GatewayUpdatesHandler { port: network.port as u32, peers, firewall_config, - mtu: network.mtu.map(|i| i as u32), - fwmark: network.fwmark.map(|i| i as u32), + mtu: network.mtu as u32, + fwmark: network.fwmark as u32, })), })), }) { @@ -583,8 +587,8 @@ impl GatewayUpdatesHandler { port: 0, peers: Vec::new(), firewall_config: None, - mtu: None, - fwmark: None, + mtu: DEFAULT_WIREGUARD_MTU as u32, + fwmark: 0, })), })), }) { diff --git a/crates/defguard_core/src/handlers/wireguard.rs b/crates/defguard_core/src/handlers/wireguard.rs index 27d729e31..fc9755c42 100644 --- a/crates/defguard_core/src/handlers/wireguard.rs +++ b/crates/defguard_core/src/handlers/wireguard.rs @@ -96,8 +96,8 @@ pub struct WireguardNetworkData { pub port: i32, pub allowed_ips: Option, pub dns: Option, - pub mtu: Option, - pub fwmark: Option, + pub mtu: i32, + pub fwmark: i64, pub allowed_groups: Vec, pub keepalive_interval: i32, pub peer_disconnect_threshold: i32, diff --git a/crates/defguard_core/src/lib.rs b/crates/defguard_core/src/lib.rs index cedb4e4fb..803a600a4 100644 --- a/crates/defguard_core/src/lib.rs +++ b/crates/defguard_core/src/lib.rs @@ -23,8 +23,8 @@ use defguard_common::{ Device, DeviceType, User, WireguardNetwork, oauth2client::OAuth2Client, wireguard::{ - DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, LocationMfaMode, - ServiceLocationMode, + DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_WIREGUARD_MTU, + LocationMfaMode, ServiceLocationMode, }, }, }, @@ -648,8 +648,8 @@ pub async fn init_dev_env(config: &DefGuardConfig) { 50051, "0.0.0.0".to_string(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, vec![IpNetwork::new(IpAddr::V4(Ipv4Addr::new(10, 1, 1, 0)), 24).unwrap()], DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, @@ -748,8 +748,8 @@ pub async fn init_vpn_location( args.port, args.endpoint.clone(), args.dns.clone(), - args.mtu.map(|i| i as i32), - args.fwmark.map(|i| i as i32), + args.mtu as i32, + i64::from(args.fwmark), args.allowed_ips.clone(), DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, @@ -790,8 +790,8 @@ pub async fn init_vpn_location( args.port, args.endpoint.clone(), args.dns.clone(), - args.mtu.map(|i| i as i32), - args.fwmark.map(|i| i as i32), + args.mtu as i32, + i64::from(args.fwmark), args.allowed_ips.clone(), DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, diff --git a/crates/defguard_core/src/wg_config.rs b/crates/defguard_core/src/wg_config.rs index 429d841d5..7f443c3db 100644 --- a/crates/defguard_core/src/wg_config.rs +++ b/crates/defguard_core/src/wg_config.rs @@ -6,8 +6,8 @@ use defguard_common::{ db::models::{ Device, WireguardNetwork, wireguard::{ - DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, LocationMfaMode, - ServiceLocationMode, + DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_WIREGUARD_MTU, + LocationMfaMode, ServiceLocationMode, }, }, }; @@ -81,21 +81,17 @@ pub(crate) fn parse_wireguard_config( .map_err(|_| WireguardConfigParseError::InvalidPort(port.to_string()))?; let dns = interface_section.get("DNS").map(ToString::to_string); let mtu = match interface_section.get("MTU") { - Some(value) => Some( - value - .parse::() - .map_err(|_| WireguardConfigParseError::InvalidMTU(value.to_string()))?, - ), - None => None, + Some(value) => value + .parse::() + .map_err(|_| WireguardConfigParseError::InvalidMTU(value.to_string()))?, + None => DEFAULT_WIREGUARD_MTU, }; // TODO: FwMark should also accept hex values. let fwmark = match interface_section.get("FwMark") { - Some(value) => Some( - value - .parse::() - .map_err(|_| WireguardConfigParseError::InvalidFwMark(value.to_string()))?, - ), - None => None, + Some(value) => value + .parse::() + .map_err(|_| WireguardConfigParseError::InvalidFwMark(value.to_string()))?, + None => 0, }; let mut addresses: Vec = Vec::new(); for addr in address.split(',') { @@ -229,8 +225,8 @@ mod test { ); assert_eq!(network.endpoint, ""); assert_eq!(network.dns, Some("10.0.0.2".to_string())); - assert_eq!(network.mtu, Some(1420)); - assert_eq!(network.fwmark, Some(51820)); + assert_eq!(network.mtu, 1420); + assert_eq!(network.fwmark, 51820); assert_eq!(network.allowed_ips, vec!["10.0.0.0/24".parse().unwrap()]); assert_eq!(network.connected_at, None); diff --git a/crates/defguard_core/tests/integration/api/acl.rs b/crates/defguard_core/tests/integration/api/acl.rs index 79d14a155..419d4fddf 100644 --- a/crates/defguard_core/tests/integration/api/acl.rs +++ b/crates/defguard_core/tests/integration/api/acl.rs @@ -6,7 +6,7 @@ use defguard_common::{ Device, DeviceType, User, WireguardNetwork, group::Group, settings::initialize_current_settings, - wireguard::{LocationMfaMode, ServiceLocationMode}, + wireguard::{DEFAULT_WIREGUARD_MTU, LocationMfaMode, ServiceLocationMode}, }, }, }; @@ -427,8 +427,8 @@ async fn test_related_objects(_: PgPoolOptions, options: PgConnectOptions) { 1000, "endpoint1".to_string(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, Vec::new(), 100, 100, @@ -770,8 +770,8 @@ async fn test_rule_delete_state_applied(_: PgPoolOptions, options: PgConnectOpti 1000, "endpoint1".to_string(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, Vec::new(), 100, 100, diff --git a/crates/defguard_core/tests/integration/api/common/mod.rs b/crates/defguard_core/tests/integration/api/common/mod.rs index 9bbac8776..225eeaf1d 100644 --- a/crates/defguard_core/tests/integration/api/common/mod.rs +++ b/crates/defguard_core/tests/integration/api/common/mod.rs @@ -187,6 +187,8 @@ pub(crate) async fn make_network(client: &TestClient, name: &str) -> TestRespons "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, diff --git a/crates/defguard_core/tests/integration/api/wireguard.rs b/crates/defguard_core/tests/integration/api/wireguard.rs index 69667beeb..a80082623 100644 --- a/crates/defguard_core/tests/integration/api/wireguard.rs +++ b/crates/defguard_core/tests/integration/api/wireguard.rs @@ -7,8 +7,8 @@ use defguard_common::db::{ device::WireguardNetworkDevice, settings::OpenIdUsernameHandling, wireguard::{ - DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, LocationMfaMode, - ServiceLocationMode, + DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_WIREGUARD_MTU, + LocationMfaMode, ServiceLocationMode, }, }, }; @@ -65,8 +65,8 @@ async fn test_network(_: PgPoolOptions, options: PgConnectOptions) { port: 55555, allowed_ips: Some("10.1.1.0/24, 10.2.0.1/16, 10.10.10.54/32".into()), dns: None, - mtu: None, - fwmark: None, + mtu: DEFAULT_WIREGUARD_MTU, + fwmark: 0, allowed_groups: vec!["admin".into()], keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, @@ -147,8 +147,8 @@ async fn test_location_mfa_mode_validation_create(_: PgPoolOptions, options: PgC port: 55555, allowed_ips: Some("10.1.1.0/24, 10.2.0.1/16, 10.10.10.54/32".into()), dns: None, - mtu: None, - fwmark: None, + mtu: DEFAULT_WIREGUARD_MTU, + fwmark: 0, allowed_groups: vec!["admin".into()], keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, @@ -231,8 +231,8 @@ async fn test_location_mfa_mode_validation_modify(_: PgPoolOptions, options: PgC port: 55555, allowed_ips: Some("10.1.1.0/24, 10.2.0.1/16, 10.10.10.54/32".into()), dns: None, - mtu: None, - fwmark: None, + mtu: DEFAULT_WIREGUARD_MTU, + fwmark: 0, allowed_groups: vec!["admin".into()], keepalive_interval: DEFAULT_KEEPALIVE_INTERVAL, peer_disconnect_threshold: DEFAULT_DISCONNECT_THRESHOLD, @@ -480,22 +480,7 @@ async fn test_network_address_reassignment(_: PgPoolOptions, options: PgConnectO assert_eq!(response.status(), StatusCode::OK); // create network - let network = json!({ - "name": "network", - "address": "10.1.1.1/24", - "port": 55555, - "endpoint": "192.168.4.14", - "allowed_ips": "10.1.1.0/24", - "dns": "1.1.1.1", - "allowed_groups": [], - "keepalive_interval": 25, - "peer_disconnect_threshold": 300, - "acl_enabled": false, - "acl_default_allow": false, - "location_mfa_mode": "disabled", - "service_location_mode": "disabled" - }); - let response = client.post("/api/v1/network").json(&network).send().await; + let response = make_network(&client, "network").await; assert_eq!(response.status(), StatusCode::CREATED); // network details @@ -556,6 +541,8 @@ async fn test_network_address_reassignment(_: PgPoolOptions, options: PgConnectO "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -839,22 +826,7 @@ async fn test_network_size_validation(_: PgPoolOptions, options: PgConnectOption assert_eq!(response.status(), StatusCode::OK); // create network - let network = json!({ - "name": "network", - "address": "10.1.1.1/24", - "port": 55555, - "endpoint": "192.168.4.14", - "allowed_ips": "10.1.1.0/24", - "dns": "1.1.1.1", - "allowed_groups": [], - "keepalive_interval": 25, - "peer_disconnect_threshold": 300, - "acl_enabled": false, - "acl_default_allow": false, - "location_mfa_mode": "disabled", - "service_location_mode": "disabled" - }); - let response = client.post("/api/v1/network").json(&network).send().await; + let response = make_network(&client, "network").await; assert_eq!(response.status(), StatusCode::CREATED); // network details @@ -903,6 +875,8 @@ async fn test_network_size_validation(_: PgPoolOptions, options: PgConnectOption "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -927,6 +901,8 @@ async fn test_network_size_validation(_: PgPoolOptions, options: PgConnectOption "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -951,6 +927,8 @@ async fn test_network_size_validation(_: PgPoolOptions, options: PgConnectOption "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, diff --git a/crates/defguard_core/tests/integration/api/wireguard_network_allowed_groups.rs b/crates/defguard_core/tests/integration/api/wireguard_network_allowed_groups.rs index 275bef35b..86f5edaa4 100644 --- a/crates/defguard_core/tests/integration/api/wireguard_network_allowed_groups.rs +++ b/crates/defguard_core/tests/integration/api/wireguard_network_allowed_groups.rs @@ -153,6 +153,8 @@ async fn test_create_new_network(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": ["allowed group"], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -202,6 +204,8 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -238,6 +242,8 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": ["allowed group"], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -268,6 +274,8 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": ["allowed group", "not allowed group"], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -299,6 +307,8 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": ["not allowed group"], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -329,6 +339,8 @@ async fn test_modify_network(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -585,6 +597,8 @@ async fn test_modify_user(_: PgPoolOptions, options: PgConnectOptions) { "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": ["allowed group"], "keepalive_interval": 25, "peer_disconnect_threshold": 300, @@ -693,6 +707,8 @@ async fn test_delete_only_allowed_group(_: PgPoolOptions, options: PgConnectOpti "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": ["allowed group"], "keepalive_interval": 25, "peer_disconnect_threshold": 300, diff --git a/crates/defguard_core/tests/integration/api/wireguard_network_devices.rs b/crates/defguard_core/tests/integration/api/wireguard_network_devices.rs index d206b083f..211e7cd33 100644 --- a/crates/defguard_core/tests/integration/api/wireguard_network_devices.rs +++ b/crates/defguard_core/tests/integration/api/wireguard_network_devices.rs @@ -15,42 +15,61 @@ use serde::Deserialize; use serde_json::{Value, json}; use sqlx::postgres::{PgConnectOptions, PgPoolOptions}; -use super::common::{make_test_client, setup_pool}; +use super::common::{ + client::{TestClient, TestResponse}, + make_test_client, setup_pool, +}; -fn make_network() -> Value { - json!({ - "name": "network", - "address": "10.1.1.1/24", - "port": 55555, - "endpoint": "192.168.4.14", - "allowed_ips": "10.1.1.0/24", - "dns": "1.1.1.1", - "allowed_groups": [], - "keepalive_interval": 25, - "peer_disconnect_threshold": 300, - "acl_enabled": false, - "acl_default_allow": false, - "location_mfa_mode": "disabled", - "service_location_mode": "disabled" - }) +async fn make_first_network(client: &TestClient) -> TestResponse { + let response = client + .post("/api/v1/network") + .json(&json!({ + "name": "network", + "address": "10.1.1.1/24", + "port": 55555, + "endpoint": "192.168.4.14", + "allowed_ips": "10.1.1.0/24", + "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, + "allowed_groups": [], + "keepalive_interval": 25, + "peer_disconnect_threshold": 300, + "acl_enabled": false, + "acl_default_allow": false, + "location_mfa_mode": "disabled", + "service_location_mode": "disabled" + })) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + response } -fn make_second_network() -> Value { - json!({ - "name": "network-2", - "address": "10.6.1.1/24", - "port": 55555, - "endpoint": "192.168.4.14", - "allowed_ips": "10.6.1.0/24", - "dns": "1.1.1.1", - "allowed_groups": [], - "keepalive_interval": 25, - "peer_disconnect_threshold": 300, - "acl_enabled": false, - "acl_default_allow": false, - "location_mfa_mode": "disabled", - "service_location_mode": "disabled" - }) +async fn make_second_network(client: &TestClient) -> TestResponse { + let response = client + .post("/api/v1/network") + .json(&json!({ + "name": "network-2", + "address": "10.6.1.1/24", + "port": 55555, + "endpoint": "192.168.4.14", + "allowed_ips": "10.6.1.0/24", + "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, + "allowed_groups": [], + "keepalive_interval": 25, + "peer_disconnect_threshold": 300, + "acl_enabled": false, + "acl_default_allow": false, + "location_mfa_mode": "disabled", + "service_location_mode": "disabled" + })) + .send() + .await; + assert_eq!(response.status(), StatusCode::CREATED); + response } #[derive(Debug, Deserialize, PartialEq)] @@ -77,22 +96,12 @@ async fn test_network_devices(_: PgPoolOptions, options: PgConnectOptions) { assert_eq!(response.status(), StatusCode::OK); // create networks - let response = client - .post("/api/v1/network") - .json(&make_network()) - .send() - .await; - assert_eq!(response.status(), StatusCode::CREATED); + let response = make_first_network(&client).await; let network_1: WireguardNetwork = response.json().await; assert_eq!(network_1.name, "network"); let event = wg_rx.try_recv().unwrap(); assert_matches!(event, GatewayEvent::NetworkCreated(..)); - let response = client - .post("/api/v1/network") - .json(&make_second_network()) - .send() - .await; - assert_eq!(response.status(), StatusCode::CREATED); + let response = make_second_network(&client).await; let network_2: WireguardNetwork = response.json().await; assert_eq!(network_2.name, "network-2"); let event = wg_rx.try_recv().unwrap(); @@ -303,6 +312,8 @@ async fn test_device_ip_validation(_: PgPoolOptions, options: PgConnectOptions) "endpoint": "192.168.4.14", "allowed_ips": "10.1.1.0/24", "dns": "1.1.1.1", + "mtu": 1420, + "fwmark": 0, "allowed_groups": [], "keepalive_interval": 25, "peer_disconnect_threshold": 300, diff --git a/crates/defguard_core/tests/integration/api/wireguard_network_import.rs b/crates/defguard_core/tests/integration/api/wireguard_network_import.rs index acf02b9c5..958f62e5a 100644 --- a/crates/defguard_core/tests/integration/api/wireguard_network_import.rs +++ b/crates/defguard_core/tests/integration/api/wireguard_network_import.rs @@ -4,8 +4,8 @@ use defguard_common::db::models::{ Device, DeviceType, WireguardNetwork, device::UserDevice, wireguard::{ - DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, LocationMfaMode, - ServiceLocationMode, + DEFAULT_DISCONNECT_THRESHOLD, DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_WIREGUARD_MTU, + LocationMfaMode, ServiceLocationMode, }, }; use defguard_core::{ @@ -56,8 +56,8 @@ async fn test_config_import(_: PgPoolOptions, options: PgConnectOptions) { 51515, String::new(), None, - None, - None, + DEFAULT_WIREGUARD_MTU, + 0, Vec::new(), DEFAULT_KEEPALIVE_INTERVAL, DEFAULT_DISCONNECT_THRESHOLD, diff --git a/e2e/package.json b/e2e/package.json index f5789344a..3e31e2427 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -12,7 +12,7 @@ "author": "", "devDependencies": { "@eslint/compat": "^1.4.0", - "@eslint/eslintrc": "^3.3.1", + "@eslint/eslintrc": "^3.3.3", "@eslint/js": "^9.36.0", "@prettier/plugin-oxc": "^0.0.4", "@types/node": "^22.18.6", @@ -22,7 +22,7 @@ "eslint": "^9.36.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-import": "^2.32.0", - "eslint-plugin-prettier": "^5.5.4", + "eslint-plugin-prettier": "^5.5.5", "eslint-plugin-simple-import-sort": "^12.1.1", "prettier": "^3.6.2" }, @@ -30,11 +30,11 @@ "@faker-js/faker": "^9.9.0", "@playwright/test": "^1.55.1", "@scure/base": "^1.2.6", - "@types/lodash": "^4.17.20", + "@types/lodash": "^4.17.23", "@types/pg": "^8.15.5", "axios": "^1.12.2", - "dotenv": "^17.2.2", - "lodash": "^4.17.21", + "dotenv": "^17.2.3", + "lodash": "^4.17.23", "pg": "^8.16.3", "playwright": "^1.55.1", "totp-generator": "^1.0.0" diff --git a/e2e/pnpm-lock.yaml b/e2e/pnpm-lock.yaml index b70d073f8..887f9e674 100644 --- a/e2e/pnpm-lock.yaml +++ b/e2e/pnpm-lock.yaml @@ -18,8 +18,8 @@ importers: specifier: ^1.2.6 version: 1.2.6 '@types/lodash': - specifier: ^4.17.20 - version: 4.17.20 + specifier: ^4.17.23 + version: 4.17.23 '@types/pg': specifier: ^8.15.5 version: 8.15.5 @@ -27,11 +27,11 @@ importers: specifier: ^1.12.2 version: 1.12.2 dotenv: - specifier: ^17.2.2 - version: 17.2.2 + specifier: ^17.2.3 + version: 17.2.3 lodash: - specifier: ^4.17.21 - version: 4.17.21 + specifier: ^4.17.23 + version: 4.17.23 pg: specifier: ^8.16.3 version: 8.16.3 @@ -46,8 +46,8 @@ importers: specifier: ^1.4.0 version: 1.4.0(eslint@9.36.0) '@eslint/eslintrc': - specifier: ^3.3.1 - version: 3.3.1 + specifier: ^3.3.3 + version: 3.3.3 '@eslint/js': specifier: ^9.36.0 version: 9.36.0 @@ -76,8 +76,8 @@ importers: specifier: ^2.32.0 version: 2.32.0(@typescript-eslint/parser@8.44.1(eslint@9.36.0)(typescript@5.8.2))(eslint@9.36.0) eslint-plugin-prettier: - specifier: ^5.5.4 - version: 5.5.4(eslint-config-prettier@10.1.8(eslint@9.36.0))(eslint@9.36.0)(prettier@3.6.2) + specifier: ^5.5.5 + version: 5.5.5(eslint-config-prettier@10.1.8(eslint@9.36.0))(eslint@9.36.0)(prettier@3.6.2) eslint-plugin-simple-import-sort: specifier: ^12.1.1 version: 12.1.1(eslint@9.36.0) @@ -131,8 +131,8 @@ packages: resolution: {integrity: sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/eslintrc@3.3.1': - resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==} + '@eslint/eslintrc@3.3.3': + resolution: {integrity: sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/js@9.36.0': @@ -305,8 +305,8 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} - '@types/lodash@4.17.20': - resolution: {integrity: sha512-H3MHACvFUEiujabxhaI/ImO6gUrd8oOurg7LQtS7mbwIXA/cUqWrvBsaeJ23aZEPk1TAYkurjfMbSELfoCXlGA==} + '@types/lodash@4.17.23': + resolution: {integrity: sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==} '@types/node@22.18.6': resolution: {integrity: sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==} @@ -533,8 +533,8 @@ packages: resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} engines: {node: '>=0.10.0'} - dotenv@17.2.2: - resolution: {integrity: sha512-Sf2LSQP+bOlhKWWyhFsn0UsfdK/kCWRv1iuA2gXAwt3dyNabr6QSj00I2V10pidqz69soatm9ZwZvpQMTIOd5Q==} + dotenv@17.2.3: + resolution: {integrity: sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==} engines: {node: '>=12'} dunder-proto@1.0.1: @@ -613,8 +613,8 @@ packages: '@typescript-eslint/parser': optional: true - eslint-plugin-prettier@5.5.4: - resolution: {integrity: sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==} + eslint-plugin-prettier@5.5.5: + resolution: {integrity: sha512-hscXkbqUZ2sPithAuLm5MXL+Wph+U7wHngPBv9OMWwlP8iaflyxpjTYZkmdgB4/vPIhemRlBEoLrH7UC1n7aUw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -932,8 +932,8 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} - js-yaml@4.1.0: - resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + js-yaml@4.1.1: + resolution: {integrity: sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==} hasBin: true json-buffer@3.0.1: @@ -966,8 +966,8 @@ packages: lodash.merge@4.6.2: resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} - lodash@4.17.21: - resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + lodash@4.17.23: + resolution: {integrity: sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==} math-intrinsics@1.1.0: resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} @@ -1136,8 +1136,8 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} - prettier-linter-helpers@1.0.0: - resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + prettier-linter-helpers@1.0.1: + resolution: {integrity: sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==} engines: {node: '>=6.0.0'} prettier@3.6.2: @@ -1272,8 +1272,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - synckit@0.11.11: - resolution: {integrity: sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==} + synckit@0.11.12: + resolution: {integrity: sha512-Bh7QjT8/SuKUIfObSXNHNSK6WHo6J1tHCqJsuaFDP7gP0fkzSfTxI8y85JrppZ0h8l0maIgc2tfuZQ6/t3GtnQ==} engines: {node: ^14.18.0 || >=16.0.0} to-regex-range@5.0.1: @@ -1412,7 +1412,7 @@ snapshots: dependencies: '@types/json-schema': 7.0.15 - '@eslint/eslintrc@3.3.1': + '@eslint/eslintrc@3.3.3': dependencies: ajv: 6.12.6 debug: 4.4.3 @@ -1420,7 +1420,7 @@ snapshots: globals: 14.0.0 ignore: 5.3.2 import-fresh: 3.3.1 - js-yaml: 4.1.0 + js-yaml: 4.1.1 minimatch: 3.1.2 strip-json-comments: 3.1.1 transitivePeerDependencies: @@ -1541,7 +1541,7 @@ snapshots: '@types/json5@0.0.29': {} - '@types/lodash@4.17.20': {} + '@types/lodash@4.17.23': {} '@types/node@22.18.6': dependencies: @@ -1836,7 +1836,7 @@ snapshots: dependencies: esutils: 2.0.3 - dotenv@17.2.2: {} + dotenv@17.2.3: {} dunder-proto@1.0.1: dependencies: @@ -1979,12 +1979,12 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-plugin-prettier@5.5.4(eslint-config-prettier@10.1.8(eslint@9.36.0))(eslint@9.36.0)(prettier@3.6.2): + eslint-plugin-prettier@5.5.5(eslint-config-prettier@10.1.8(eslint@9.36.0))(eslint@9.36.0)(prettier@3.6.2): dependencies: eslint: 9.36.0 prettier: 3.6.2 - prettier-linter-helpers: 1.0.0 - synckit: 0.11.11 + prettier-linter-helpers: 1.0.1 + synckit: 0.11.12 optionalDependencies: eslint-config-prettier: 10.1.8(eslint@9.36.0) @@ -2008,7 +2008,7 @@ snapshots: '@eslint/config-array': 0.21.0 '@eslint/config-helpers': 0.3.1 '@eslint/core': 0.15.2 - '@eslint/eslintrc': 3.3.1 + '@eslint/eslintrc': 3.3.3 '@eslint/js': 9.36.0 '@eslint/plugin-kit': 0.3.5 '@humanfs/node': 0.16.7 @@ -2322,7 +2322,7 @@ snapshots: isexe@2.0.0: {} - js-yaml@4.1.0: + js-yaml@4.1.1: dependencies: argparse: 2.0.1 @@ -2353,7 +2353,7 @@ snapshots: lodash.merge@4.6.2: {} - lodash@4.17.21: {} + lodash@4.17.23: {} math-intrinsics@1.1.0: {} @@ -2529,7 +2529,7 @@ snapshots: prelude-ls@1.2.1: {} - prettier-linter-helpers@1.0.0: + prettier-linter-helpers@1.0.1: dependencies: fast-diff: 1.3.0 @@ -2694,7 +2694,7 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - synckit@0.11.11: + synckit@0.11.12: dependencies: '@pkgr/core': 0.2.9 diff --git a/migrations/20251218140442_[2.0.0]_core_ca.down.sql b/migrations/20251218140442_[2.0.0]_core_ca.down.sql new file mode 100644 index 000000000..22ee3452f --- /dev/null +++ b/migrations/20251218140442_[2.0.0]_core_ca.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE settings + DROP COLUMN ca_key_der, + DROP COLUMN ca_cert_der; diff --git a/migrations/20251218140442_[2.0.0]_core_ca.up.sql b/migrations/20251218140442_[2.0.0]_core_ca.up.sql new file mode 100644 index 000000000..3db71200f --- /dev/null +++ b/migrations/20251218140442_[2.0.0]_core_ca.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE settings + ADD COLUMN ca_key_der BYTEA DEFAULT NULL, + ADD COLUMN ca_cert_der BYTEA DEFAULT NULL; diff --git a/migrations/20251218140442_core_ca.down.sql b/migrations/20251218140442_core_ca.down.sql deleted file mode 100644 index 070c45ebb..000000000 --- a/migrations/20251218140442_core_ca.down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE settings DROP COLUMN ca_key_der; -ALTER TABLE settings DROP COLUMN ca_cert_der; diff --git a/migrations/20251218140442_core_ca.up.sql b/migrations/20251218140442_core_ca.up.sql deleted file mode 100644 index eb1daffd0..000000000 --- a/migrations/20251218140442_core_ca.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE settings ADD COLUMN ca_key_der BYTEA DEFAULT NULL; -ALTER TABLE settings ADD COLUMN ca_cert_der BYTEA DEFAULT NULL; diff --git a/migrations/20260107092015_[2.0.0]_mtu_fwmark.down.sql b/migrations/20260107092015_[2.0.0]_mtu_fwmark.down.sql new file mode 100644 index 000000000..2368ce0c6 --- /dev/null +++ b/migrations/20260107092015_[2.0.0]_mtu_fwmark.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE wireguard_network + DROP COLUMN mtu, + DROP COLUMN fwmark; diff --git a/migrations/20260107092015_[2.0.0]_mtu_fwmark.up.sql b/migrations/20260107092015_[2.0.0]_mtu_fwmark.up.sql new file mode 100644 index 000000000..faf70e012 --- /dev/null +++ b/migrations/20260107092015_[2.0.0]_mtu_fwmark.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE wireguard_network + ADD COLUMN mtu integer NOT NULL DEFAULT 1420, + ADD COLUMN fwmark bigint NOT NULL DEFAULT 0; diff --git a/migrations/20260107092015_mtu_fwmark.down.sql b/migrations/20260107092015_mtu_fwmark.down.sql deleted file mode 100644 index 91080b23f..000000000 --- a/migrations/20260107092015_mtu_fwmark.down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE wireguard_network DROP COLUMN mtu; -ALTER TABLE wireguard_network DROP COLUMN fwmark; diff --git a/migrations/20260107092015_mtu_fwmark.up.sql b/migrations/20260107092015_mtu_fwmark.up.sql deleted file mode 100644 index 39422ab48..000000000 --- a/migrations/20260107092015_mtu_fwmark.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE wireguard_network ADD COLUMN mtu integer NULL; -ALTER TABLE wireguard_network ADD COLUMN fwmark integer NULL; diff --git a/migrations/20260113094304_[2.0.0]_gateway_certificates_management.down.sql b/migrations/20260113094304_[2.0.0]_gateway_certificates_management.down.sql new file mode 100644 index 000000000..2b52bcba7 --- /dev/null +++ b/migrations/20260113094304_[2.0.0]_gateway_certificates_management.down.sql @@ -0,0 +1,3 @@ +ALTER TABLE gateway + DROP COLUMN has_certificate, + DROP COLUMN certificate_expiry; diff --git a/migrations/20260113094304_[2.0.0]_gateway_certificates_management.up.sql b/migrations/20260113094304_[2.0.0]_gateway_certificates_management.up.sql new file mode 100644 index 000000000..602117547 --- /dev/null +++ b/migrations/20260113094304_[2.0.0]_gateway_certificates_management.up.sql @@ -0,0 +1,3 @@ +ALTER TABLE gateway + ADD COLUMN has_certificate boolean NOT NULL DEFAULT false, + ADD COLUMN certificate_expiry timestamp without time zone NULL; diff --git a/migrations/20260113094304_gateway_certificates_management.down.sql b/migrations/20260113094304_gateway_certificates_management.down.sql deleted file mode 100644 index fa9a52941..000000000 --- a/migrations/20260113094304_gateway_certificates_management.down.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE gateway DROP COLUMN has_certificate; -ALTER TABLE gateway DROP COLUMN certificate_expiry; diff --git a/migrations/20260113094304_gateway_certificates_management.up.sql b/migrations/20260113094304_gateway_certificates_management.up.sql deleted file mode 100644 index aa5825457..000000000 --- a/migrations/20260113094304_gateway_certificates_management.up.sql +++ /dev/null @@ -1,2 +0,0 @@ -ALTER TABLE gateway ADD COLUMN has_certificate boolean NOT NULL DEFAULT false; -ALTER TABLE gateway ADD COLUMN certificate_expiry timestamp without time zone NULL; diff --git a/migrations/20260113114719_proxy_management.down.sql b/migrations/20260113114719_[2.0.0]_proxy_management.down.sql similarity index 100% rename from migrations/20260113114719_proxy_management.down.sql rename to migrations/20260113114719_[2.0.0]_proxy_management.down.sql diff --git a/migrations/20260113114719_proxy_management.up.sql b/migrations/20260113114719_[2.0.0]_proxy_management.up.sql similarity index 100% rename from migrations/20260113114719_proxy_management.up.sql rename to migrations/20260113114719_[2.0.0]_proxy_management.up.sql diff --git a/proto b/proto index ec48aca94..906412eb5 160000 --- a/proto +++ b/proto @@ -1 +1 @@ -Subproject commit ec48aca9438e7cdcb4fcdb01ce6dcb5dac7f8dd3 +Subproject commit 906412eb50ac605f4904a355c2f325f3645c117e diff --git a/web/package.json b/web/package.json index 02380890a..9d7383bb8 100644 --- a/web/package.json +++ b/web/package.json @@ -20,12 +20,9 @@ "@shortercode/webzip": "1.1.1-0", "@stablelib/base64": "^2.0.1", "@stablelib/x25519": "^2.0.1", - "@tanstack/react-devtools": "^0.9.2", "@tanstack/react-form": "^1.27.7", - "@tanstack/react-query": "^5.90.17", - "@tanstack/react-query-devtools": "^5.91.2", + "@tanstack/react-query": "^5.90.19", "@tanstack/react-router": "^1.149.3", - "@tanstack/react-router-devtools": "^1.149.3", "@tanstack/react-table": "^8.21.3", "@tanstack/react-virtual": "^3.13.18", "@uidotdev/usehooks": "^2.4.1", @@ -36,39 +33,42 @@ "easy-file-picker": "^1.2.0", "humanize-duration": "^3.33.2", "ipaddr.js": "^2.3.0", - "lodash-es": "^4.17.22", + "lodash-es": "^4.17.23", "motion": "^12.26.2", "qrcode.react": "^4.2.0", "qs": "^6.14.1", "react": "^19.2.3", "react-dom": "^19.2.3", - "react-intersection-observer": "^10.0.0", + "react-intersection-observer": "^10.0.2", "react-loading-skeleton": "^3.5.0", "react-markdown": "^10.1.0", "recharts": "^3.6.0", "rehype-raw": "^7.0.0", "rxjs": "^7.8.2", - "text-case": "^1.2.9", - "zod": "^4.3.5", + "text-case": "^1.2.10", + "zod": "^4.3.6", "zustand": "^5.0.10" }, "devDependencies": { "@biomejs/biome": "2.3.11", "@inlang/paraglide-js": "2.8.0", "@tanstack/devtools-vite": "^0.4.1", + "@tanstack/react-devtools": "^0.9.2", + "@tanstack/react-query-devtools": "^5.91.2", + "@tanstack/react-router-devtools": "^1.149.3", "@tanstack/router-plugin": "^1.149.3", "@types/byte-size": "^8.1.2", "@types/humanize-duration": "^3.27.4", "@types/lodash-es": "^4.17.12", - "@types/node": "^25.0.8", + "@types/node": "^25.0.10", "@types/qs": "^6.14.0", - "@types/react": "^19.2.8", + "@types/react": "^19.2.9", "@types/react-dom": "^19.2.3", "@vitejs/plugin-react-swc": "^4.2.2", "autoprefixer": "^10.4.23", "globals": "^17.0.0", "prettier": "^3.7.4", - "sass": "^1.97.2", + "sass": "^1.97.3", "sharp": "^0.34.5", "stylelint": "^16.26.1", "stylelint-config-standard-scss": "^16.0.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 788f93983..fdffdface 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@axa-ch/react-polymorphic-types': specifier: ^1.4.1 - version: 1.4.1(@types/react@19.2.8)(react@19.2.3) + version: 1.4.1(@types/react@19.2.9)(react@19.2.3) '@floating-ui/react': specifier: ^0.27.16 version: 0.27.16(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -29,24 +29,15 @@ importers: '@stablelib/x25519': specifier: ^2.0.1 version: 2.0.1 - '@tanstack/react-devtools': - specifier: ^0.9.2 - version: 0.9.2(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.9) '@tanstack/react-form': specifier: ^1.27.7 version: 1.27.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-query': - specifier: ^5.90.17 - version: 5.90.17(react@19.2.3) - '@tanstack/react-query-devtools': - specifier: ^5.91.2 - version: 5.91.2(@tanstack/react-query@5.90.17(react@19.2.3))(react@19.2.3) + specifier: ^5.90.19 + version: 5.90.19(react@19.2.3) '@tanstack/react-router': specifier: ^1.149.3 version: 1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - '@tanstack/react-router-devtools': - specifier: ^1.149.3 - version: 1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.149.3)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/react-table': specifier: ^8.21.3 version: 8.21.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -78,8 +69,8 @@ importers: specifier: ^2.3.0 version: 2.3.0 lodash-es: - specifier: ^4.17.22 - version: 4.17.22 + specifier: ^4.17.23 + version: 4.17.23 motion: specifier: ^12.26.2 version: 12.26.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -96,17 +87,17 @@ importers: specifier: ^19.2.3 version: 19.2.3(react@19.2.3) react-intersection-observer: - specifier: ^10.0.0 - version: 10.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3) + specifier: ^10.0.2 + version: 10.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) react-loading-skeleton: specifier: ^3.5.0 version: 3.5.0(react@19.2.3) react-markdown: specifier: ^10.1.0 - version: 10.1.0(@types/react@19.2.8)(react@19.2.3) + version: 10.1.0(@types/react@19.2.9)(react@19.2.3) recharts: specifier: ^3.6.0 - version: 3.6.0(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.0)(react@19.2.3)(redux@5.0.1) + version: 3.6.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.0)(react@19.2.3)(redux@5.0.1) rehype-raw: specifier: ^7.0.0 version: 7.0.0 @@ -114,24 +105,33 @@ importers: specifier: ^7.8.2 version: 7.8.2 text-case: - specifier: ^1.2.9 - version: 1.2.9 + specifier: ^1.2.10 + version: 1.2.10 zod: - specifier: ^4.3.5 - version: 4.3.5 + specifier: ^4.3.6 + version: 4.3.6 zustand: specifier: ^5.0.10 - version: 5.0.10(@types/react@19.2.8)(immer@11.1.3)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) + version: 5.0.10(@types/react@19.2.9)(immer@11.1.3)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)) devDependencies: '@biomejs/biome': specifier: 2.3.11 version: 2.3.11 '@tanstack/devtools-vite': specifier: ^0.4.1 - version: 0.4.1(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0)) + version: 0.4.1(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0)) + '@tanstack/react-devtools': + specifier: ^0.9.2 + version: 0.9.2(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.9) + '@tanstack/react-query-devtools': + specifier: ^5.91.2 + version: 5.91.2(@tanstack/react-query@5.90.19(react@19.2.3))(react@19.2.3) + '@tanstack/react-router-devtools': + specifier: ^1.149.3 + version: 1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.149.3)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3) '@tanstack/router-plugin': specifier: ^1.149.3 - version: 1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0)) + version: 1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0)) '@types/byte-size': specifier: ^8.1.2 version: 8.1.2 @@ -142,20 +142,20 @@ importers: specifier: ^4.17.12 version: 4.17.12 '@types/node': - specifier: ^25.0.8 - version: 25.0.8 + specifier: ^25.0.10 + version: 25.0.10 '@types/qs': specifier: ^6.14.0 version: 6.14.0 '@types/react': - specifier: ^19.2.8 - version: 19.2.8 + specifier: ^19.2.9 + version: 19.2.9 '@types/react-dom': specifier: ^19.2.3 - version: 19.2.3(@types/react@19.2.8) + version: 19.2.3(@types/react@19.2.9) '@vitejs/plugin-react-swc': specifier: ^4.2.2 - version: 4.2.2(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0)) + version: 4.2.2(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0)) autoprefixer: specifier: ^10.4.23 version: 10.4.23(postcss@8.5.6) @@ -166,8 +166,8 @@ importers: specifier: ^3.7.4 version: 3.7.4 sass: - specifier: ^1.97.2 - version: 1.97.2 + specifier: ^1.97.3 + version: 1.97.3 sharp: specifier: ^0.34.5 version: 0.34.5 @@ -185,10 +185,10 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0) + version: 7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0) vite-plugin-image-optimizer: specifier: ^2.0.3 - version: 2.0.3(sharp@0.34.5)(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0)) + version: 2.0.3(sharp@0.34.5)(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0)) packages: @@ -1164,8 +1164,8 @@ packages: resolution: {integrity: sha512-y/xtNPNt/YeyoVxE/JCx+T7yjEzpezmbb+toK8DDD1P4m7Kzs5YR956+7OKexG3f8aXgC3rLZl7b1V+yNUSy5w==} engines: {node: '>=18'} - '@tanstack/query-core@5.90.17': - resolution: {integrity: sha512-hDww+RyyYhjhUfoYQ4es6pbgxY7LNiPWxt4l1nJqhByjndxJ7HIjDxTBtfvMr5HwjYavMrd+ids5g4Rfev3lVQ==} + '@tanstack/query-core@5.90.19': + resolution: {integrity: sha512-GLW5sjPVIvH491VV1ufddnfldyVB+teCnpPIvweEfkpRx7CfUmUGhoh9cdcUKBh/KwVxk22aNEDxeTsvmyB/WA==} '@tanstack/query-devtools@5.92.0': resolution: {integrity: sha512-N8D27KH1vEpVacvZgJL27xC6yPFUy0Zkezn5gnB3L3gRCxlDeSuiya7fKge8Y91uMTnC8aSxBQhcK6ocY7alpQ==} @@ -1194,8 +1194,8 @@ packages: '@tanstack/react-query': ^5.90.14 react: ^18 || ^19 - '@tanstack/react-query@5.90.17': - resolution: {integrity: sha512-PGc2u9KLwohDUSchjW9MZqeDQJfJDON7y4W7REdNBgiFKxQy+Pf7eGjiFWEj5xPqKzAeHYdAb62IWI1a9UJyGQ==} + '@tanstack/react-query@5.90.19': + resolution: {integrity: sha512-qTZRZ4QyTzQc+M0IzrbKHxSeISUmRB3RPGmao5bT+sI6ayxSRhn0FXEnT5Hg3as8SBFcRosrXXRFB+yAcxVxJQ==} peerDependencies: react: ^18 || ^19 @@ -1354,8 +1354,8 @@ packages: '@types/ms@2.1.0': resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} - '@types/node@25.0.8': - resolution: {integrity: sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg==} + '@types/node@25.0.10': + resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==} '@types/qs@6.14.0': resolution: {integrity: sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==} @@ -1365,8 +1365,8 @@ packages: peerDependencies: '@types/react': ^19.2.0 - '@types/react@19.2.8': - resolution: {integrity: sha512-3MbSL37jEchWZz2p2mjntRZtPt837ij10ApxKfgmXCTuHWagYg7iA5bqPw6C8BMPfwidlvfPI/fxOc42HLhcyg==} + '@types/react@19.2.9': + resolution: {integrity: sha512-Lpo8kgb/igvMIPeNV2rsYKTgaORYdO1XGVZ4Qz3akwOj0ySGYMPlQWa8BaLn0G63D1aSaAQ5ldR06wCpChQCjA==} '@types/unist@2.0.11': resolution: {integrity: sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==} @@ -2078,8 +2078,8 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} - lodash-es@4.17.22: - resolution: {integrity: sha512-XEawp1t0gxSi9x01glktRZ5HDy0HXqrM0x5pXQM98EaI0NxO6jVM7omDOxsuEo5UIASAnm2bRp1Jt/e0a2XU8Q==} + lodash-es@4.17.23: + resolution: {integrity: sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==} lodash.truncate@4.4.2: resolution: {integrity: sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==} @@ -2345,8 +2345,8 @@ packages: peerDependencies: react: ^19.2.3 - react-intersection-observer@10.0.0: - resolution: {integrity: sha512-JJRgcnFQoVXmbE5+GXr1OS1NDD1gHk0HyfpLcRf0575IbJz+io8yzs4mWVlfaqOQq1FiVjLvuYAdEEcrrCfveg==} + react-intersection-observer@10.0.2: + resolution: {integrity: sha512-lAMzxVWrBko6SLd1jx6l84fVrzJu91hpxHlvD2as2Wec9mDCjdYXwc5xNOFBchpeBir0Y7AGBW+C/AYMa7CSFg==} peerDependencies: react: ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^17.0.0 || ^18.0.0 || ^19.0.0 @@ -2454,8 +2454,8 @@ packages: rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} - sass@1.97.2: - resolution: {integrity: sha512-y5LWb0IlbO4e97Zr7c3mlpabcbBtS+ieiZ9iwDooShpFKWXf62zz5pEPdwrLYm+Bxn1fnbwFGzHuCLSA9tBmrw==} + sass@1.97.3: + resolution: {integrity: sha512-fDz1zJpd5GycprAbu4Q2PV/RprsRtKC/0z82z0JLgdytmcq0+ujJbJ/09bPGDxCLkKY3Np5cRAOcWiVkLXJURg==} engines: {node: '>=14.0.0'} hasBin: true @@ -2628,68 +2628,68 @@ packages: resolution: {integrity: sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==} engines: {node: '>=10.0.0'} - text-camel-case@1.2.9: - resolution: {integrity: sha512-wKYs9SgRxYizJE1mneR7BbLNlGw2IYzJAS8XwkWIry0CTbO1gvvPkFsx5Z1/hr+VqUaBqx9q3yKd30HpZLdMsQ==} + text-camel-case@1.2.10: + resolution: {integrity: sha512-KNrWeZzQT+gh73V1LnmgTkjK7V+tMRjLCc6VrGwkqbiRdnGVIWBUgIvVnvnaVCxIvZ/2Ke8DCmgPirlQcCqD3Q==} - text-capital-case@1.2.9: - resolution: {integrity: sha512-X5zV8U8pxtq2xS2t46lgAWqZdDbgWMKq03MQSNwY2CJdQCsdTNh144E2Q/q9wBxWzSBUXn+jRc9kF+Gs8/pGhA==} + text-capital-case@1.2.10: + resolution: {integrity: sha512-yvViUJKSSQcRO58je224bhPHg/Hij9MEY43zuKShtFzrPwW/fOAarUJ5UkTMSB81AOO1m8q+JiFdxMF4etKZbA==} - text-case@1.2.9: - resolution: {integrity: sha512-zZVdA8rMcjx9zhekdUuOPZShc25UTV7W8/ddKbgbPtfCEvIiToPtWiSd2lXLSuiGMovNhJ4+Tw49xll9o9ts+Q==} + text-case@1.2.10: + resolution: {integrity: sha512-5bY3Ks/u7OJ5YO69iyXrG5Xf2wUZeyko7U78nPUnYoSeuNeAfA5uAix5hTspfkl6smm3yCBObrex+kFvzeIcJg==} - text-constant-case@1.2.9: - resolution: {integrity: sha512-Vosm6nC7Gag+JFakJHwqS9AXRNgl07j5KZ7srU9cYuKRzYwrxzeJ4RpEogRBNHw7CfmOm0j5FGEznblWtu7pIw==} + text-constant-case@1.2.10: + resolution: {integrity: sha512-/OfU798O2wrwKN9kQf71WhJeAlklGnbby0Tupp+Ez9NXymW+6oF9LWDRTkN+OreTmHucdvp4WQd6O5Rah5zj8A==} - text-dot-case@1.2.9: - resolution: {integrity: sha512-N83hsnvGdSO9q9AfNSB9Cy1LFDNN2MCx53LcxtaPoDWPUTk47fv0JlvIY1tgY0wyzCiThF03kVj3jworvAOScA==} + text-dot-case@1.2.10: + resolution: {integrity: sha512-vf4xguy5y6e39RlDZeWZFMDf2mNkR23VTSVb9e68dUSpfJscG9/1YWWpW3n8TinzQxBZlsn5sT5olL33MvvQXw==} - text-header-case@1.2.9: - resolution: {integrity: sha512-TqryEKcYisQAfWLbtT3xPnZlMZ/mySO1uS+LUg+B0eNuqgETrSzVpXIUj5E6Zf/EyJHgpZf4VndbAXtOMJuT4w==} + text-header-case@1.2.10: + resolution: {integrity: sha512-sVb1NY9bwxtu+Z7CVyWbr+I0AkWtF0kEHL/Zz5V2u/WdkjK5tKBwl5nXf0NGy9da4ZUYTBb+TmQpOIqihzvFMQ==} - text-is-lower-case@1.2.9: - resolution: {integrity: sha512-cEurrWSnYVYqL8FSwl5cK4mdfqF7qNDCcKJgXI3NnfTesiB8umxAhdlQoErrRYI1xEvYr2WN0MI333EehUhQjg==} + text-is-lower-case@1.2.10: + resolution: {integrity: sha512-dMTeTgrdWWfYf3fKxvjMkDPuXWv96cWbd1Uym6Zjv9H855S1uHxjkFsGbTYJ2tEK0NvAylRySTQlI6axlcMc4w==} - text-is-upper-case@1.2.9: - resolution: {integrity: sha512-HxsWr3VCsXXiLlhD0c+Ey+mS2lOTCiSJbkepjaXNHl2bp33KiscQaiG0qLwQmmpZQm4SJCg2s9FkndxS0RNDLQ==} + text-is-upper-case@1.2.10: + resolution: {integrity: sha512-PGD/cXoXECGAY1HVZxDdmpJUW2ZUAKQ6DTamDfCHC9fc/z4epOz0pB/ThBnjJA3fz+d2ApkMjAfZDjuZFcodzg==} - text-kebab-case@1.2.9: - resolution: {integrity: sha512-nOUyNR5Ej2B9D/wyyXfwUEv26+pQuOb1pEX+ojE37mCIWo8QeOxw5y6nxuqDmG7NrEPzbO6265UMV+EICH13Cw==} + text-kebab-case@1.2.10: + resolution: {integrity: sha512-3XZJAApx5JQpUO7eXo7GQ2TyRcGw3OVbqxz6QJb2h+N8PbLLbz3zJVeXdGrhTkoUIbkSZ6PmHx6LRDaHXTdMcA==} - text-lower-case-first@1.2.9: - resolution: {integrity: sha512-iiphHTV7PVH0MljrEQUA9iBE7jfDpXoi4RQju3WzZU3BRVbS6540cNZgxR19hWa0z6z/7cJTH0Ls9LPBaiUfKg==} + text-lower-case-first@1.2.10: + resolution: {integrity: sha512-Oro84jZPDLD9alfdZWmtFHYTvCaaSz2o4thPtjMsK4GAkTyVg9juYXWj0y0YFyjLYGH69muWsBe4/MR5S7iolw==} - text-lower-case@1.2.9: - resolution: {integrity: sha512-53AOnDrhPpiAUQkgY1SHleKUXp/u7GsqRX13NcCREZscmtjLLJ099uxMRjkK7q2KwHkFYVPl9ytkQlTkTQLS0w==} + text-lower-case@1.2.10: + resolution: {integrity: sha512-c9j5pIAN3ObAp1+4R7970e1bgtahTRF/5ZQdX2aJBuBngYTYZZIck0NwFXUKk5BnYpLGsre5KFHvpqvf4IYKgg==} - text-no-case@1.2.9: - resolution: {integrity: sha512-IcCt328KaapimSrytP4ThfC8URmHZb2DgOqCL9BYvGjpxY2lDiqCkIQk9sClZtwcELs2gTnq83a7jNc573FTLA==} + text-no-case@1.2.10: + resolution: {integrity: sha512-4/m79pzQrywrwEG5lCULY1lQvFY+EKjhH9xSMT6caPK5plqzm9Y7rXyv+UXPd3s9qH6QODZnvsAYWW3M0JgxRA==} - text-param-case@1.2.9: - resolution: {integrity: sha512-nR/Ju9amY3aQS1en2CUCgqN/ZiZIVdDyjlJ3xX5J92ChBevGuA4o9K10fh3JGMkbzK97Vcb+bWQJ4Q+Svz+GyQ==} + text-param-case@1.2.10: + resolution: {integrity: sha512-hkavcLsRRzZcGryPAshct1AwIOMj/FexYjMaLpGZCYYBn1lcZEeyMzJZPSckzkOYpq35LYSQr3xZto9XU5OAsw==} - text-pascal-case@1.2.9: - resolution: {integrity: sha512-o6ZxMGjWDTUW54pcghpXes+C2PqbYRMdU5mHrIhueb6z6nq1NueiIOeCUdrSjN/3wXfhCmnFjK7/d9aRGZNqSg==} + text-pascal-case@1.2.10: + resolution: {integrity: sha512-/kynZD8vTYOmm/RECjIDaz3qYEUZc/N/bnC79XuAFxwXjdNVjj/jGovKJLRzqsYK/39N22XpGcVmGg7yIrbk6w==} - text-path-case@1.2.9: - resolution: {integrity: sha512-s8cJ6r5TkJp5ticXMgtxd7f12odEN4d1CfX5u4aoz6jcUtBR2lDqzIhVimkqWFMJ4UKPSrmilUha8Xc2BPi+ow==} + text-path-case@1.2.10: + resolution: {integrity: sha512-vbKdRCaVEeOaW6sm24QP9NbH7TS9S4ZQ3u19H8eylDox7m2HtFwYIBjAPv+v3z4I/+VjrMy9LB54lNP1uEqRHw==} - text-sentence-case@1.2.9: - resolution: {integrity: sha512-/G/Yi5kZfUa1edFRV4O3lGZAkbDZTFvlwW8CYfH7szkEGe2k2MYEYbOyAkGRVQEGV6V6JiuUAaP3VS9c1tB6nQ==} + text-sentence-case@1.2.10: + resolution: {integrity: sha512-NO4MRlbfxFhl9QgQLuCL4xHmvE7PUWHVPWsZxQ5nzRtDjXOUllWvtsvl8CP5tBEvBmzg0kwfflxfhRtr5vBQGg==} - text-snake-case@1.2.9: - resolution: {integrity: sha512-+ZrqK19ynF/TLQZ7ynqVrL2Dy04uu9syYZwsm8PhzUdsY3XrwPy6QiRqhIEFqhyWbShPcfyfmheer5UEQqFxlw==} + text-snake-case@1.2.10: + resolution: {integrity: sha512-6ttMZ+B9jkHKun908HYr4xSvEtlbfJJ4MvpQ06JEKRGhwjMI0x8t2Wywp+MEzN6142O6E/zKhra18KyBL6cvXA==} - text-swap-case@1.2.9: - resolution: {integrity: sha512-g5fp12ldktYKK9wdHRMvvtSCQrZYNv/D+ZGLumDsvAY4q9T5bCMO2IWMkIP1F5gVQrysdHH6Xv877P/pjUq1iw==} + text-swap-case@1.2.10: + resolution: {integrity: sha512-vO3jwInIk0N77oEFakYZ2Hn/llTmRwf2c3RvkX/LfvmLWVp+3QcIc6bwUEtbqGQ5Xh2okjFhYrfkHZstVc3N4Q==} - text-title-case@1.2.9: - resolution: {integrity: sha512-RAtC9cdmPp41ns5/HXZBsaQg71BsHT7uZpj2ojTtuFa8o2dNuRYYOrSmy5YdLRIAJQ6WK5hQVpV3jHuq7a+4Tw==} + text-title-case@1.2.10: + resolution: {integrity: sha512-bqA+WWexUMWu9A3fdNar+3GXXW+c5xOvMyuK5hOx/w0AlqhyQptyCrMFjGB8Fd9dxbryBNmJ+5rWtC1OBDxlaA==} - text-upper-case-first@1.2.9: - resolution: {integrity: sha512-wEDD1B6XqJmEV+xEnBJd+2sBCHZ+7fvA/8Rv/o8+dAsp05YWjYP/kjB8sPH6zqzW0s6jtehIg4IlcKjcYxk2CQ==} + text-upper-case-first@1.2.10: + resolution: {integrity: sha512-VXs7j7BbpKwvolDh5fwpYRmMrUHGkxbY8E90fhBzKUoKfadvWmPT/jFieoZ4UPLzr208pXvQEFbb2zO9Qzs9Fg==} - text-upper-case@1.2.9: - resolution: {integrity: sha512-K/0DNT7a4z8eah2spARtoJllTZyrNTo6Uc0ujhN/96Ir9uJ/slpahfs13y46H9osL3daaLl3O7iXOkW4xtX6bg==} + text-upper-case@1.2.10: + resolution: {integrity: sha512-L1AtZ8R+jtSMTq0Ffma9R4Rzbrc3iuYW89BmWFH41AwnDfRmEBlBOllm1ZivRLQ/6pEu2p+3XKBHx9fsMl2CWg==} tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} @@ -2871,8 +2871,8 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} - zod@4.3.5: - resolution: {integrity: sha512-k7Nwx6vuWx1IJ9Bjuf4Zt1PEllcwe7cls3VNzm4CQ1/hgtFUK2bRNG3rvnpPUhFjmqJKAKtjV576KnUkHocg/g==} + zod@4.3.6: + resolution: {integrity: sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==} zustand@5.0.10: resolution: {integrity: sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg==} @@ -2897,9 +2897,9 @@ packages: snapshots: - '@axa-ch/react-polymorphic-types@1.4.1(@types/react@19.2.8)(react@19.2.3)': + '@axa-ch/react-polymorphic-types@1.4.1(@types/react@19.2.9)(react@19.2.3)': dependencies: - '@types/react': 19.2.8 + '@types/react': 19.2.9 react: 19.2.3 '@babel/code-frame@7.28.6': @@ -3438,7 +3438,7 @@ snapshots: '@react-hook/passive-layout-effect': 1.2.1(react@19.2.3) react: 19.2.3 - '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.8)(react@19.2.3)(redux@5.0.1))(react@19.2.3)': + '@reduxjs/toolkit@2.11.2(react-redux@9.2.0(@types/react@19.2.9)(react@19.2.3)(redux@5.0.1))(react@19.2.3)': dependencies: '@standard-schema/spec': 1.1.0 '@standard-schema/utils': 0.3.0 @@ -3448,7 +3448,7 @@ snapshots: reselect: 5.1.1 optionalDependencies: react: 19.2.3 - react-redux: 9.2.0(@types/react@19.2.8)(react@19.2.3)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.9)(react@19.2.3)(redux@5.0.1) '@rolldown/pluginutils@1.0.0-beta.47': {} @@ -3671,7 +3671,7 @@ snapshots: transitivePeerDependencies: - csstype - '@tanstack/devtools-vite@0.4.1(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0))': + '@tanstack/devtools-vite@0.4.1(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0))': dependencies: '@babel/core': 7.28.6 '@babel/generator': 7.28.6 @@ -3683,7 +3683,7 @@ snapshots: chalk: 5.6.2 launch-editor: 2.12.0 picomatch: 4.0.3 - vite: 7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0) transitivePeerDependencies: - bufferutil - supports-color @@ -3715,15 +3715,15 @@ snapshots: '@tanstack/pacer-lite@0.1.1': {} - '@tanstack/query-core@5.90.17': {} + '@tanstack/query-core@5.90.19': {} '@tanstack/query-devtools@5.92.0': {} - '@tanstack/react-devtools@0.9.2(@types/react-dom@19.2.3(@types/react@19.2.8))(@types/react@19.2.8)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.9)': + '@tanstack/react-devtools@0.9.2(@types/react-dom@19.2.3(@types/react@19.2.9))(@types/react@19.2.9)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(solid-js@1.9.9)': dependencies: '@tanstack/devtools': 0.10.3(csstype@3.2.3)(solid-js@1.9.9) - '@types/react': 19.2.8 - '@types/react-dom': 19.2.3(@types/react@19.2.8) + '@types/react': 19.2.9 + '@types/react-dom': 19.2.3(@types/react@19.2.9) react: 19.2.3 react-dom: 19.2.3(react@19.2.3) transitivePeerDependencies: @@ -3740,15 +3740,15 @@ snapshots: transitivePeerDependencies: - react-dom - '@tanstack/react-query-devtools@5.91.2(@tanstack/react-query@5.90.17(react@19.2.3))(react@19.2.3)': + '@tanstack/react-query-devtools@5.91.2(@tanstack/react-query@5.90.19(react@19.2.3))(react@19.2.3)': dependencies: '@tanstack/query-devtools': 5.92.0 - '@tanstack/react-query': 5.90.17(react@19.2.3) + '@tanstack/react-query': 5.90.19(react@19.2.3) react: 19.2.3 - '@tanstack/react-query@5.90.17(react@19.2.3)': + '@tanstack/react-query@5.90.19(react@19.2.3)': dependencies: - '@tanstack/query-core': 5.90.17 + '@tanstack/query-core': 5.90.19 react: 19.2.3 '@tanstack/react-router-devtools@1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(@tanstack/router-core@1.149.3)(csstype@3.2.3)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)': @@ -3824,7 +3824,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@tanstack/router-plugin@1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0))': + '@tanstack/router-plugin@1.149.3(@tanstack/react-router@1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0))': dependencies: '@babel/core': 7.28.6 '@babel/plugin-syntax-jsx': 7.28.6(@babel/core@7.28.6) @@ -3842,7 +3842,7 @@ snapshots: zod: 3.25.76 optionalDependencies: '@tanstack/react-router': 1.149.3(react-dom@19.2.3(react@19.2.3))(react@19.2.3) - vite: 7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0) transitivePeerDependencies: - supports-color @@ -3922,17 +3922,17 @@ snapshots: '@types/ms@2.1.0': {} - '@types/node@25.0.8': + '@types/node@25.0.10': dependencies: undici-types: 7.16.0 '@types/qs@6.14.0': {} - '@types/react-dom@19.2.3(@types/react@19.2.8)': + '@types/react-dom@19.2.3(@types/react@19.2.9)': dependencies: - '@types/react': 19.2.8 + '@types/react': 19.2.9 - '@types/react@19.2.8': + '@types/react@19.2.9': dependencies: csstype: 3.2.3 @@ -3949,11 +3949,11 @@ snapshots: '@ungap/structured-clone@1.3.0': {} - '@vitejs/plugin-react-swc@4.2.2(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0))': + '@vitejs/plugin-react-swc@4.2.2(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0))': dependencies: '@rolldown/pluginutils': 1.0.0-beta.47 '@swc/core': 1.15.8 - vite: 7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0) transitivePeerDependencies: - '@swc/helpers' @@ -4604,7 +4604,7 @@ snapshots: lines-and-columns@1.2.4: {} - lodash-es@4.17.22: {} + lodash-es@4.17.23: {} lodash.truncate@4.4.2: {} @@ -4971,7 +4971,7 @@ snapshots: react: 19.2.3 scheduler: 0.27.0 - react-intersection-observer@10.0.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3): + react-intersection-observer@10.0.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3): dependencies: react: 19.2.3 optionalDependencies: @@ -4983,11 +4983,11 @@ snapshots: dependencies: react: 19.2.3 - react-markdown@10.1.0(@types/react@19.2.8)(react@19.2.3): + react-markdown@10.1.0(@types/react@19.2.9)(react@19.2.3): dependencies: '@types/hast': 3.0.4 '@types/mdast': 4.0.4 - '@types/react': 19.2.8 + '@types/react': 19.2.9 devlop: 1.1.0 hast-util-to-jsx-runtime: 2.3.6 html-url-attributes: 3.0.1 @@ -5001,13 +5001,13 @@ snapshots: transitivePeerDependencies: - supports-color - react-redux@9.2.0(@types/react@19.2.8)(react@19.2.3)(redux@5.0.1): + react-redux@9.2.0(@types/react@19.2.9)(react@19.2.3)(redux@5.0.1): dependencies: '@types/use-sync-external-store': 0.0.6 react: 19.2.3 use-sync-external-store: 1.6.0(react@19.2.3) optionalDependencies: - '@types/react': 19.2.8 + '@types/react': 19.2.9 redux: 5.0.1 react@19.2.3: {} @@ -5026,9 +5026,9 @@ snapshots: tiny-invariant: 1.3.3 tslib: 2.8.1 - recharts@3.6.0(@types/react@19.2.8)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.0)(react@19.2.3)(redux@5.0.1): + recharts@3.6.0(@types/react@19.2.9)(react-dom@19.2.3(react@19.2.3))(react-is@19.2.0)(react@19.2.3)(redux@5.0.1): dependencies: - '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.8)(react@19.2.3)(redux@5.0.1))(react@19.2.3) + '@reduxjs/toolkit': 2.11.2(react-redux@9.2.0(@types/react@19.2.9)(react@19.2.3)(redux@5.0.1))(react@19.2.3) clsx: 2.1.1 decimal.js-light: 2.5.1 es-toolkit: 1.43.0 @@ -5037,7 +5037,7 @@ snapshots: react: 19.2.3 react-dom: 19.2.3(react@19.2.3) react-is: 19.2.0 - react-redux: 9.2.0(@types/react@19.2.8)(react@19.2.3)(redux@5.0.1) + react-redux: 9.2.0(@types/react@19.2.9)(react@19.2.3)(redux@5.0.1) reselect: 5.1.1 tiny-invariant: 1.3.3 use-sync-external-store: 1.6.0(react@19.2.3) @@ -5126,7 +5126,7 @@ snapshots: dependencies: tslib: 2.8.1 - sass@1.97.2: + sass@1.97.3: dependencies: chokidar: 4.0.3 immutable: 5.1.4 @@ -5369,98 +5369,98 @@ snapshots: string-width: 4.2.3 strip-ansi: 6.0.1 - text-camel-case@1.2.9: + text-camel-case@1.2.10: dependencies: - text-pascal-case: 1.2.9 + text-pascal-case: 1.2.10 - text-capital-case@1.2.9: + text-capital-case@1.2.10: dependencies: - text-no-case: 1.2.9 - text-upper-case-first: 1.2.9 + text-no-case: 1.2.10 + text-upper-case-first: 1.2.10 - text-case@1.2.9: + text-case@1.2.10: dependencies: - text-camel-case: 1.2.9 - text-capital-case: 1.2.9 - text-constant-case: 1.2.9 - text-dot-case: 1.2.9 - text-header-case: 1.2.9 - text-is-lower-case: 1.2.9 - text-is-upper-case: 1.2.9 - text-kebab-case: 1.2.9 - text-lower-case: 1.2.9 - text-lower-case-first: 1.2.9 - text-no-case: 1.2.9 - text-param-case: 1.2.9 - text-pascal-case: 1.2.9 - text-path-case: 1.2.9 - text-sentence-case: 1.2.9 - text-snake-case: 1.2.9 - text-swap-case: 1.2.9 - text-title-case: 1.2.9 - text-upper-case: 1.2.9 - text-upper-case-first: 1.2.9 + text-camel-case: 1.2.10 + text-capital-case: 1.2.10 + text-constant-case: 1.2.10 + text-dot-case: 1.2.10 + text-header-case: 1.2.10 + text-is-lower-case: 1.2.10 + text-is-upper-case: 1.2.10 + text-kebab-case: 1.2.10 + text-lower-case: 1.2.10 + text-lower-case-first: 1.2.10 + text-no-case: 1.2.10 + text-param-case: 1.2.10 + text-pascal-case: 1.2.10 + text-path-case: 1.2.10 + text-sentence-case: 1.2.10 + text-snake-case: 1.2.10 + text-swap-case: 1.2.10 + text-title-case: 1.2.10 + text-upper-case: 1.2.10 + text-upper-case-first: 1.2.10 - text-constant-case@1.2.9: + text-constant-case@1.2.10: dependencies: - text-no-case: 1.2.9 - text-upper-case: 1.2.9 + text-no-case: 1.2.10 + text-upper-case: 1.2.10 - text-dot-case@1.2.9: + text-dot-case@1.2.10: dependencies: - text-no-case: 1.2.9 + text-no-case: 1.2.10 - text-header-case@1.2.9: + text-header-case@1.2.10: dependencies: - text-capital-case: 1.2.9 + text-capital-case: 1.2.10 - text-is-lower-case@1.2.9: {} + text-is-lower-case@1.2.10: {} - text-is-upper-case@1.2.9: {} + text-is-upper-case@1.2.10: {} - text-kebab-case@1.2.9: + text-kebab-case@1.2.10: dependencies: - text-no-case: 1.2.9 + text-no-case: 1.2.10 - text-lower-case-first@1.2.9: {} + text-lower-case-first@1.2.10: {} - text-lower-case@1.2.9: {} + text-lower-case@1.2.10: {} - text-no-case@1.2.9: + text-no-case@1.2.10: dependencies: - text-lower-case: 1.2.9 + text-lower-case: 1.2.10 - text-param-case@1.2.9: + text-param-case@1.2.10: dependencies: - text-dot-case: 1.2.9 + text-dot-case: 1.2.10 - text-pascal-case@1.2.9: + text-pascal-case@1.2.10: dependencies: - text-no-case: 1.2.9 + text-no-case: 1.2.10 - text-path-case@1.2.9: + text-path-case@1.2.10: dependencies: - text-dot-case: 1.2.9 + text-dot-case: 1.2.10 - text-sentence-case@1.2.9: + text-sentence-case@1.2.10: dependencies: - text-no-case: 1.2.9 - text-upper-case-first: 1.2.9 + text-no-case: 1.2.10 + text-upper-case-first: 1.2.10 - text-snake-case@1.2.9: + text-snake-case@1.2.10: dependencies: - text-dot-case: 1.2.9 + text-dot-case: 1.2.10 - text-swap-case@1.2.9: {} + text-swap-case@1.2.10: {} - text-title-case@1.2.9: + text-title-case@1.2.10: dependencies: - text-no-case: 1.2.9 - text-upper-case-first: 1.2.9 + text-no-case: 1.2.10 + text-upper-case-first: 1.2.10 - text-upper-case-first@1.2.9: {} + text-upper-case-first@1.2.10: {} - text-upper-case@1.2.9: {} + text-upper-case@1.2.10: {} tiny-invariant@1.3.3: {} @@ -5582,15 +5582,15 @@ snapshots: d3-time: 3.1.0 d3-timer: 3.0.1 - vite-plugin-image-optimizer@2.0.3(sharp@0.34.5)(vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0)): + vite-plugin-image-optimizer@2.0.3(sharp@0.34.5)(vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0)): dependencies: ansi-colors: 4.1.3 pathe: 2.0.3 - vite: 7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0) optionalDependencies: sharp: 0.34.5 - vite@7.3.1(@types/node@25.0.8)(sass@1.97.2)(tsx@4.21.0): + vite@7.3.1(@types/node@25.0.10)(sass@1.97.3)(tsx@4.21.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.3) @@ -5599,9 +5599,9 @@ snapshots: rollup: 4.55.1 tinyglobby: 0.2.15 optionalDependencies: - '@types/node': 25.0.8 + '@types/node': 25.0.10 fsevents: 2.3.3 - sass: 1.97.2 + sass: 1.97.3 tsx: 4.21.0 web-namespaces@2.0.1: {} @@ -5623,11 +5623,11 @@ snapshots: zod@3.25.76: {} - zod@4.3.5: {} + zod@4.3.6: {} - zustand@5.0.10(@types/react@19.2.8)(immer@11.1.3)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)): + zustand@5.0.10(@types/react@19.2.9)(immer@11.1.3)(react@19.2.3)(use-sync-external-store@1.6.0(react@19.2.3)): optionalDependencies: - '@types/react': 19.2.8 + '@types/react': 19.2.9 immer: 11.1.3 react: 19.2.3 use-sync-external-store: 1.6.0(react@19.2.3) diff --git a/web/src/pages/AddLocationPage/steps/AddLocationNetworkStep.tsx b/web/src/pages/AddLocationPage/steps/AddLocationNetworkStep.tsx index 9c480c617..5157086e5 100644 --- a/web/src/pages/AddLocationPage/steps/AddLocationNetworkStep.tsx +++ b/web/src/pages/AddLocationPage/steps/AddLocationNetworkStep.tsx @@ -13,8 +13,8 @@ const formSchema = z.object({ keepalive_interval: z .number(m.form_error_required()) .max(65535, m.form_error_port_max()), - mtu: z.number().nullable(), - fwmark: z.number().nullable(), + mtu: z.number(m.form_error_required()).min(72).max(0xffffffff), + fwmark: z.number(m.form_error_required()).min(0).max(0xffffffff), }); type FormFields = z.infer; diff --git a/web/src/pages/AddLocationPage/useAddLocationStore.tsx b/web/src/pages/AddLocationPage/useAddLocationStore.tsx index 3f38f92ca..e680ad1d2 100644 --- a/web/src/pages/AddLocationPage/useAddLocationStore.tsx +++ b/web/src/pages/AddLocationPage/useAddLocationStore.tsx @@ -25,8 +25,8 @@ const defaults: StoreValues = { name: '', port: 50051, keepalive_interval: 25, - mtu: null, - fwmark: null, + mtu: 1420, + fwmark: 0, peer_disconnect_threshold: 300, acl_default_allow: true, acl_enabled: false, diff --git a/web/src/pages/EditLocationPage/EditLocationPage.tsx b/web/src/pages/EditLocationPage/EditLocationPage.tsx index f4057fd4d..662a6c133 100644 --- a/web/src/pages/EditLocationPage/EditLocationPage.tsx +++ b/web/src/pages/EditLocationPage/EditLocationPage.tsx @@ -80,8 +80,8 @@ const formSchema = z.object({ keepalive_interval: z .number(m.form_error_required()) .max(65535, m.form_error_port_max()), - mtu: z.number().nullable(), - fwmark: z.number().nullable(), + mtu: z.number(m.form_error_required()).min(72).max(0xffffffff), + fwmark: z.number(m.form_error_required()).min(0).max(0xffffffff), allowed_groups: z.array( z.string(m.form_error_required()).trim().min(1, m.form_error_required()), ), diff --git a/web/src/shared/api/types.ts b/web/src/shared/api/types.ts index 461171723..6e21e748d 100644 --- a/web/src/shared/api/types.ts +++ b/web/src/shared/api/types.ts @@ -485,8 +485,8 @@ export interface NetworkLocation { allowed_groups: string[]; dns: string | null; keepalive_interval: number; - mtu: number | null; - fwmark: number | null; + mtu: number; + fwmark: number; peer_disconnect_threshold: number; acl_enabled: boolean; acl_default_allow: boolean;