mirror of
https://github.com/DaLaw2/NetGuardia.git
synced 2026-08-24 14:10:28 +09:00
chore: pin Rust 1.95 toolchain, externalize size caps, stabilize audit
Toolchain + clippy 1.95: - rust-toolchain.toml: pin channel 1.95.0 with clippy + rustfmt - websocket/flow_websocket.rs: collapse nested if into if-let guard - secret_store.rs: feed Nonce::from_exact_iter the Vec directly (IntoIterator coercion replaces explicit .into_iter()) - statistics.rs: sort_by_key with std::cmp::Reverse over sort_by Externalize hardcoded ceilings into InferenceConfig + DB settings so admins can tune them without a rebuild: - Flow Trace rotation: max_file_bytes (500MB), max_file_age_secs (1h), total_budget_bytes (10GB) - Model upload caps: max_onnx_bytes (100MB), max_manifest_bytes (64KB), max_scaler_bytes (64KB) Default seed lives in app_config.rs; the rest is plumbed through InferenceConfig and consumed by traffic_logger.rs + model_upload.rs. Stabilize WORM audit chain identifiers behind named constants so downstream tooling that filters on these strings is shielded from casual rename refactors: - model_upload.rs: AUDIT_ACTOR_SECURITY_ADMIN_PREFIX, AUDIT_ACTION_MODEL_SWAP - traffic_logger.rs: AUDIT_ACTOR_SYSTEM, AUDIT_ACTION_FLOW_TRACE_STOPPED Janitorial: - model_upload.rs + traffic_logger.rs: hoist std::fs to `use std::fs as std_fs;` so call sites stay within the inline-path-depth-2 cap - soar/playbook.rs: drop now-stale #[allow(dead_code)] on PlaybookAction::action_order — matcher reads it via simulate_playbook Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d502eb8c60
commit
8c0a313a68
308
Cargo.lock
generated
308
Cargo.lock
generated
@ -473,15 +473,6 @@ version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "170433209e817da6aae2c51aa0dd443009a613425dd041ebfb2492d1c4c11a25"
|
||||
|
||||
[[package]]
|
||||
name = "ar_archive_writer"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eb93bbb63b9c227414f6eb3a0adfddca591a8ce1e9b60661bb08969b87e340b"
|
||||
dependencies = [
|
||||
"object 0.37.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.9.1"
|
||||
@ -544,7 +535,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"libc",
|
||||
"log",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"once_cell",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
@ -655,7 +646,7 @@ dependencies = [
|
||||
"core-error",
|
||||
"hashbrown 0.15.5",
|
||||
"log",
|
||||
"object 0.36.7",
|
||||
"object",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
@ -819,9 +810,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.57"
|
||||
version = "1.2.60"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a0dd1ca384932ff3641c8718a02769f1698e7563dc6974ffd03346116310423"
|
||||
checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
|
||||
dependencies = [
|
||||
"find-msvc-tools",
|
||||
"jobserver",
|
||||
@ -872,16 +863,6 @@ dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "chumsky"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
|
||||
dependencies = [
|
||||
"hashbrown 0.14.5",
|
||||
"stacker",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cipher"
|
||||
version = "0.4.4"
|
||||
@ -1321,7 +1302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1338,9 +1319,9 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.3.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
|
||||
checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
@ -1561,7 +1542,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1586,6 +1566,12 @@ dependencies = [
|
||||
"foldhash 0.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.10.0"
|
||||
@ -1694,9 +1680,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
|
||||
|
||||
[[package]]
|
||||
name = "hyper"
|
||||
version = "1.8.1"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
|
||||
checksum = "6299f016b246a94207e63da54dbe807655bf9e00044f73ded42c3ac5305fbcca"
|
||||
dependencies = [
|
||||
"atomic-waker",
|
||||
"bytes",
|
||||
@ -1707,7 +1693,6 @@ dependencies = [
|
||||
"httparse",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"pin-utils",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
"want",
|
||||
@ -1747,7 +1732,7 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2 0.6.3",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@ -1779,12 +1764,13 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_collections"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
|
||||
checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"potential_utf",
|
||||
"utf8_iter",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
"zerovec",
|
||||
@ -1792,9 +1778,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_locale_core"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
|
||||
checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"litemap",
|
||||
@ -1805,9 +1791,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
|
||||
checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4"
|
||||
dependencies = [
|
||||
"icu_collections",
|
||||
"icu_normalizer_data",
|
||||
@ -1819,15 +1805,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_normalizer_data"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
|
||||
checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38"
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties"
|
||||
version = "2.1.2"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec"
|
||||
checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de"
|
||||
dependencies = [
|
||||
"icu_collections",
|
||||
"icu_locale_core",
|
||||
@ -1839,15 +1825,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "icu_properties_data"
|
||||
version = "2.1.2"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af"
|
||||
checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14"
|
||||
|
||||
[[package]]
|
||||
name = "icu_provider"
|
||||
version = "2.1.1"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
|
||||
checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"icu_locale_core",
|
||||
@ -1899,12 +1885,12 @@ checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.13.0"
|
||||
version = "2.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017"
|
||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.16.1",
|
||||
"hashbrown 0.17.0",
|
||||
"serde",
|
||||
"serde_core",
|
||||
]
|
||||
@ -1972,9 +1958,9 @@ checksum = "cf370abdafd54d13e54a620e8c3e1145f28e46cc9d704bc6d94414559df41763"
|
||||
|
||||
[[package]]
|
||||
name = "iri-string"
|
||||
version = "0.7.10"
|
||||
version = "0.7.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a"
|
||||
checksum = "25e659a4bb38e810ebc252e53b5814ff908a8c58c2a9ce2fae1bbec24cbf4e20"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
"serde",
|
||||
@ -2024,9 +2010,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.17"
|
||||
version = "1.0.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2"
|
||||
checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
@ -2040,10 +2026,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.91"
|
||||
version = "0.3.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c"
|
||||
checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@ -2113,13 +2101,12 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2"
|
||||
|
||||
[[package]]
|
||||
name = "lettre"
|
||||
version = "0.11.19"
|
||||
version = "0.11.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e13e10e8818f8b2a60f52cb127041d388b89f3a96a62be9ceaffa22262fef7f"
|
||||
checksum = "dabda5859ee7c06b995b9d1165aa52c39110e079ef609db97178d86aeb051fa7"
|
||||
dependencies = [
|
||||
"async-trait",
|
||||
"base64",
|
||||
"chumsky",
|
||||
"email-encoding",
|
||||
"email_address",
|
||||
"fastrand",
|
||||
@ -2175,14 +2162,14 @@ checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.14"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a"
|
||||
checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
"libc",
|
||||
"plain",
|
||||
"redox_syscall 0.7.3",
|
||||
"redox_syscall 0.7.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -2269,9 +2256,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "litemap"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
|
||||
checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0"
|
||||
|
||||
[[package]]
|
||||
name = "local-channel"
|
||||
@ -2438,9 +2425,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.1.1"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc"
|
||||
checksum = "50b7e5b27aa02a74bac8c3f23f448f8d87ff11f92d3aac1a6ed369ee08cc56c1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
@ -2672,9 +2659,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.2.0"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050"
|
||||
checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
@ -2747,15 +2734,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.37.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.21.4"
|
||||
@ -2885,12 +2863,6 @@ version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
|
||||
|
||||
[[package]]
|
||||
name = "pin-utils"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.32"
|
||||
@ -2932,9 +2904,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "potential_utf"
|
||||
version = "0.1.4"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
|
||||
checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564"
|
||||
dependencies = [
|
||||
"zerovec",
|
||||
]
|
||||
@ -3017,16 +2989,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "psm"
|
||||
version = "0.1.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3852766467df634d74f0b2d7819bf8dc483a0eb2e3b0f50f756f9cfe8b0d18d8"
|
||||
dependencies = [
|
||||
"ar_archive_writer",
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quinn"
|
||||
version = "0.11.9"
|
||||
@ -3040,7 +3002,7 @@ dependencies = [
|
||||
"quinn-udp",
|
||||
"rustc-hash",
|
||||
"rustls",
|
||||
"socket2 0.6.3",
|
||||
"socket2 0.5.10",
|
||||
"thiserror 2.0.18",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@ -3077,9 +3039,9 @@ dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2 0.6.3",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3093,9 +3055,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quoted_printable"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73"
|
||||
checksum = "478e0585659a122aa407eb7e3c0e1fa51b1d8a870038bd29f0cf4a8551eea972"
|
||||
|
||||
[[package]]
|
||||
name = "r-efi"
|
||||
@ -3234,9 +3196,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.7.3"
|
||||
version = "0.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce70a74e890531977d37e532c34d45e9055d2409ed08ddba14529471ed0be16"
|
||||
checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a"
|
||||
dependencies = [
|
||||
"bitflags 2.11.0",
|
||||
]
|
||||
@ -3378,9 +3340,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "2.1.1"
|
||||
version = "2.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||
checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe"
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
@ -3415,7 +3377,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3520,9 +3482,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.27"
|
||||
version = "1.0.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
|
||||
checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_core",
|
||||
@ -3582,9 +3544,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_spanned"
|
||||
version = "1.0.4"
|
||||
version = "1.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776"
|
||||
checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
@ -3663,9 +3625,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "simd-adler32"
|
||||
version = "0.3.8"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
|
||||
checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214"
|
||||
|
||||
[[package]]
|
||||
name = "simple_asn1"
|
||||
@ -3717,19 +3679,6 @@ version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
|
||||
|
||||
[[package]]
|
||||
name = "stacker"
|
||||
version = "0.1.23"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "08d74a23609d509411d10e2176dc2a4346e3b4aea2e7b1869f19fdedbc71c013"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"psm",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
@ -3829,9 +3778,9 @@ checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||
|
||||
[[package]]
|
||||
name = "tar"
|
||||
version = "0.4.44"
|
||||
version = "0.4.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a"
|
||||
checksum = "22692a6476a21fa75fdfc11d452fda482af402c008cdbaf3476414e122040973"
|
||||
dependencies = [
|
||||
"filetime",
|
||||
"libc",
|
||||
@ -3845,10 +3794,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd"
|
||||
dependencies = [
|
||||
"fastrand",
|
||||
"getrandom 0.4.2",
|
||||
"getrandom 0.3.4",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3933,9 +3882,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
|
||||
checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"zerovec",
|
||||
@ -4022,9 +3971,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.0.7+spec-1.1.0"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd28d57d8a6f6e458bc0b8784f8fdcc4b99a437936056fa122cb234f18656a96"
|
||||
checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde_core",
|
||||
@ -4037,27 +3986,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "toml_datetime"
|
||||
version = "1.0.1+spec-1.1.0"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
|
||||
checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7"
|
||||
dependencies = [
|
||||
"serde_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_parser"
|
||||
version = "1.0.10+spec-1.1.0"
|
||||
version = "1.1.2+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7df25b4befd31c4816df190124375d5a20c6b6921e2cad937316de3fccd63420"
|
||||
checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526"
|
||||
dependencies = [
|
||||
"winnow",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml_writer"
|
||||
version = "1.0.7+spec-1.1.0"
|
||||
version = "1.1.1+spec-1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f17aaa1c6e3dc22b1da4b6bba97d066e354c7945cac2f7852d4e4e7ca7a6b56d"
|
||||
checksum = "756daf9b1013ebe47a8776667b466417e2d4c5679d441c26230efd9ef78692db"
|
||||
|
||||
[[package]]
|
||||
name = "tower"
|
||||
@ -4389,9 +4338,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
|
||||
checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-xid"
|
||||
@ -4532,9 +4481,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.114"
|
||||
version = "0.2.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6532f9a5c1ece3798cb1c2cfdba640b9b3ba884f5db45973a6f442510a87d38e"
|
||||
checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
@ -4545,23 +4494,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-futures"
|
||||
version = "0.4.64"
|
||||
version = "0.4.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9c5522b3a28661442748e09d40924dfb9ca614b21c00d3fd135720e48b67db8"
|
||||
checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"futures-util",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"wasm-bindgen",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.114"
|
||||
version = "0.2.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "18a2d50fcf105fb33bb15f00e7a77b772945a2ee45dcf454961fd843e74c18e6"
|
||||
checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -4569,9 +4514,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.114"
|
||||
version = "0.2.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03ce4caeaac547cdf713d280eda22a730824dd11e6b8c3ca9e42247b25c631e3"
|
||||
checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"proc-macro2",
|
||||
@ -4582,9 +4527,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.114"
|
||||
version = "0.2.118"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75a326b8c223ee17883a4251907455a2431acc2791c98c26279376490c378c16"
|
||||
checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@ -4625,9 +4570,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.91"
|
||||
version = "0.3.95"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854ba17bb104abfb26ba36da9729addc7ce7f06f5c0f90f3c391f8461cca21f9"
|
||||
checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
@ -4683,7 +4628,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.61.2",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4802,15 +4747,6 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.61.2"
|
||||
@ -4895,9 +4831,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a90e88e4667264a994d34e6d1ab2d26d398dcdca8b7f52bec8668957517fc7d8"
|
||||
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
|
||||
|
||||
[[package]]
|
||||
name = "wit-bindgen"
|
||||
@ -4989,9 +4925,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "writeable"
|
||||
version = "0.6.2"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
|
||||
checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4"
|
||||
|
||||
[[package]]
|
||||
name = "xattr"
|
||||
@ -5018,9 +4954,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "yoke"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
|
||||
checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca"
|
||||
dependencies = [
|
||||
"stable_deref_trait",
|
||||
"yoke-derive",
|
||||
@ -5029,9 +4965,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "yoke-derive"
|
||||
version = "0.8.1"
|
||||
version = "0.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
|
||||
checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5041,18 +4977,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.42"
|
||||
version = "0.8.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2578b716f8a7a858b7f02d5bd870c14bf4ddbbcf3a4c05414ba6503640505e3"
|
||||
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.42"
|
||||
version = "0.8.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e6cc098ea4d3bd6246687de65af3f920c430e236bee1e3bf2e441463f08a02f"
|
||||
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5061,18 +4997,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
|
||||
checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df"
|
||||
dependencies = [
|
||||
"zerofrom-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom-derive"
|
||||
version = "0.1.6"
|
||||
version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
|
||||
checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -5088,9 +5024,9 @@ checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
|
||||
[[package]]
|
||||
name = "zerotrie"
|
||||
version = "0.2.3"
|
||||
version = "0.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
|
||||
checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"yoke",
|
||||
@ -5099,9 +5035,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.5"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
|
||||
checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
|
||||
dependencies = [
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
@ -5110,9 +5046,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zerovec-derive"
|
||||
version = "0.11.2"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
|
||||
checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@ -1 +1 @@
|
||||
Subproject commit a2a78812e368a79ebbe688265764a295e33635bd
|
||||
Subproject commit 0e600c5f4956aa599beff09413011b088e848fe9
|
||||
@ -7,22 +7,30 @@
|
||||
//! entry records the SHA-256 of both committed files plus a snapshot
|
||||
//! of the pre-swap state.
|
||||
//!
|
||||
//! Body-size caps: 100MB ONNX, 64KB manifest, 64KB scaler. Streaming
|
||||
//! writes never buffer the full file in RAM, and staged directories
|
||||
//! are torn down on any error path so failed uploads don't pile up in
|
||||
//! Body-size caps come from `InferenceConfig::model_upload_max_*_bytes`
|
||||
//! so admins can tune them from the settings DB without a rebuild.
|
||||
//! Defaults: 100MB ONNX, 64KB manifest, 64KB scaler. Streaming writes
|
||||
//! never buffer the full file in RAM, and staged directories are torn
|
||||
//! down on any error path so failed uploads don't pile up in
|
||||
//! `models/.staging/`.
|
||||
|
||||
use std::fs as std_fs;
|
||||
use std::fs::File as StdFile;
|
||||
use std::io;
|
||||
use std::io::Read;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, SystemTime};
|
||||
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{HttpResponse, Responder, Scope, web};
|
||||
use futures_util::TryStreamExt;
|
||||
use serde_json::Value as JsonValue;
|
||||
use sha2::{Digest, Sha256};
|
||||
use tokio::fs;
|
||||
use tokio::io::AsyncWriteExt;
|
||||
use tokio::sync::Mutex as AsyncMutex;
|
||||
use tokio::task;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::core::auth::extractor::AuthClaims;
|
||||
@ -35,20 +43,6 @@ use crate::model::config::constants::{MANIFEST_FILENAME, MODELS_DIR, STAGING_SUB
|
||||
use crate::model::event::AuditEvent;
|
||||
use crate::model::system::config::MLInferenceConfig;
|
||||
|
||||
/// Hard ceiling on the `.onnx` stream. Anything larger is either a
|
||||
/// mistake or an attempt to DoS the disk.
|
||||
pub const MAX_ONNX_BYTES: usize = 100 * 1024 * 1024;
|
||||
|
||||
/// Hard ceiling on the `manifest` YAML stream. Real manifests are a few
|
||||
/// kilobytes at most; this leaves headroom without allowing blob
|
||||
/// smuggling through the field.
|
||||
pub const MAX_MANIFEST_BYTES: usize = 64 * 1024;
|
||||
|
||||
/// Hard ceiling on the optional `scaler` JSON sidecar. Sidecars are
|
||||
/// numeric arrays keyed to feature count; 64KB fits any realistic
|
||||
/// feature set many times over.
|
||||
pub const MAX_SCALER_BYTES: usize = 64 * 1024;
|
||||
|
||||
/// Multipart field names the client must use. Stable wire contract —
|
||||
/// the frontend form generator depends on these exact strings.
|
||||
const FIELD_MANIFEST: &str = "manifest";
|
||||
@ -67,6 +61,20 @@ const ONNX_SNIFF_BYTES: usize = 16;
|
||||
/// swap the ML source.
|
||||
const PROMOTE_REQUIRED_PERMISSION: &str = "users:admin";
|
||||
|
||||
/// Actor prefix on the WORM `model_swap` audit entry. Administrators
|
||||
/// that trigger the upload endpoint land on the chain as
|
||||
/// `SecurityAdmin@<username>` so downstream filters can separate
|
||||
/// system-driven entries (actor="system") from human-driven ones
|
||||
/// without parsing free-form text. Stable across releases — renaming
|
||||
/// breaks downstream audit tooling that filters on this prefix.
|
||||
const AUDIT_ACTOR_SECURITY_ADMIN_PREFIX: &str = "SecurityAdmin";
|
||||
|
||||
/// Action recorded on the WORM chain when a promote succeeds. Stable
|
||||
/// wire string — fusion-explain tooling and future "who swapped the
|
||||
/// model" views filter on it, so the rename must go through the audit
|
||||
/// chain too.
|
||||
const AUDIT_ACTION_MODEL_SWAP: &str = "model_swap";
|
||||
|
||||
/// Process-wide lock serializing the rename step of every promote.
|
||||
/// The critical section is tiny (three `tokio::fs::rename` syscalls)
|
||||
/// but must never interleave: a concurrent promote mid-rename could
|
||||
@ -102,7 +110,12 @@ async fn upload(
|
||||
let staging_id = Uuid::new_v4().to_string();
|
||||
let staging_dir = staging_root.join(&staging_id);
|
||||
|
||||
let summary = match ingest_multipart(payload, &staging_dir).await {
|
||||
let caps = UploadCaps {
|
||||
manifest: app_config.inference.model_upload_max_manifest_bytes,
|
||||
onnx: app_config.inference.model_upload_max_onnx_bytes,
|
||||
scaler: app_config.inference.model_upload_max_scaler_bytes,
|
||||
};
|
||||
let summary = match ingest_multipart(payload, &staging_dir, caps).await {
|
||||
Ok(s) => s,
|
||||
Err(e) => {
|
||||
let _ = fs::remove_dir_all(&staging_dir).await;
|
||||
@ -154,16 +167,29 @@ struct UploadSummary {
|
||||
scaler_bytes: Option<usize>,
|
||||
}
|
||||
|
||||
/// Per-field byte caps. Plumbed from `InferenceConfig` through the
|
||||
/// handler so admins can tune caps from the DB without a code change.
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct UploadCaps {
|
||||
manifest: usize,
|
||||
onnx: usize,
|
||||
scaler: usize,
|
||||
}
|
||||
|
||||
/// Errors that can surface a specific HTTP response. Kept in-module
|
||||
/// because none of these have callers outside this handler.
|
||||
///
|
||||
/// The `*TooLarge(usize)` variants carry the admin-configured cap so
|
||||
/// the response can tell the client which ceiling they hit without
|
||||
/// having to query `/api/config` separately.
|
||||
#[derive(Debug)]
|
||||
enum UploadError {
|
||||
MissingField(&'static str),
|
||||
DuplicateField(&'static str),
|
||||
UnknownField(String),
|
||||
ManifestTooLarge,
|
||||
OnnxTooLarge,
|
||||
ScalerTooLarge,
|
||||
ManifestTooLarge(usize),
|
||||
OnnxTooLarge(usize),
|
||||
ScalerTooLarge(usize),
|
||||
OnnxNotBinary,
|
||||
StreamFailure(String),
|
||||
StagingSetupFailure(String),
|
||||
@ -175,9 +201,9 @@ impl UploadError {
|
||||
Self::MissingField(name) => (400, format!("missing required multipart field: {name}")),
|
||||
Self::DuplicateField(name) => (400, format!("multipart field sent twice: {name}")),
|
||||
Self::UnknownField(name) => (400, format!("unexpected multipart field: {name}")),
|
||||
Self::ManifestTooLarge => (413, format!("manifest exceeds {MAX_MANIFEST_BYTES} bytes")),
|
||||
Self::OnnxTooLarge => (413, format!("onnx exceeds {MAX_ONNX_BYTES} bytes")),
|
||||
Self::ScalerTooLarge => (413, format!("scaler exceeds {MAX_SCALER_BYTES} bytes")),
|
||||
Self::ManifestTooLarge(max_bytes) => (413, format!("manifest exceeds {max_bytes} bytes")),
|
||||
Self::OnnxTooLarge(max_bytes) => (413, format!("onnx exceeds {max_bytes} bytes")),
|
||||
Self::ScalerTooLarge(max_bytes) => (413, format!("scaler exceeds {max_bytes} bytes")),
|
||||
Self::OnnxNotBinary => (
|
||||
400,
|
||||
"onnx field does not look like a protobuf-encoded ONNX model".to_string(),
|
||||
@ -194,7 +220,11 @@ impl UploadError {
|
||||
}
|
||||
}
|
||||
|
||||
async fn ingest_multipart(mut payload: Multipart, staging_dir: &Path) -> Result<UploadSummary, UploadError> {
|
||||
async fn ingest_multipart(
|
||||
mut payload: Multipart,
|
||||
staging_dir: &Path,
|
||||
caps: UploadCaps,
|
||||
) -> Result<UploadSummary, UploadError> {
|
||||
fs::create_dir_all(staging_dir)
|
||||
.await
|
||||
.map_err(|e| UploadError::StagingSetupFailure(e.to_string()))?;
|
||||
@ -219,7 +249,7 @@ async fn ingest_multipart(mut payload: Multipart, staging_dir: &Path) -> Result<
|
||||
return Err(UploadError::DuplicateField(FIELD_MANIFEST));
|
||||
}
|
||||
let dest = staging_dir.join(MANIFEST_FILENAME);
|
||||
let written = stream_field_to_file(&mut field, &dest, MAX_MANIFEST_BYTES, FieldKind::Manifest).await?;
|
||||
let written = stream_field_to_file(&mut field, &dest, caps.manifest, FieldKind::Manifest).await?;
|
||||
manifest_written = Some(written);
|
||||
}
|
||||
FIELD_ONNX => {
|
||||
@ -232,7 +262,7 @@ async fn ingest_multipart(mut payload: Multipart, staging_dir: &Path) -> Result<
|
||||
.map(sanitize_filename)
|
||||
.unwrap_or_else(|| "model.onnx".to_string());
|
||||
let dest = staging_dir.join(&onnx_filename);
|
||||
let written = stream_field_to_file(&mut field, &dest, MAX_ONNX_BYTES, FieldKind::Onnx).await?;
|
||||
let written = stream_field_to_file(&mut field, &dest, caps.onnx, FieldKind::Onnx).await?;
|
||||
onnx_summary = Some((onnx_filename, written));
|
||||
}
|
||||
FIELD_SCALER => {
|
||||
@ -245,7 +275,7 @@ async fn ingest_multipart(mut payload: Multipart, staging_dir: &Path) -> Result<
|
||||
.map(sanitize_filename)
|
||||
.unwrap_or_else(|| "inference_config.json".to_string());
|
||||
let dest = staging_dir.join(&scaler_filename);
|
||||
let written = stream_field_to_file(&mut field, &dest, MAX_SCALER_BYTES, FieldKind::Scaler).await?;
|
||||
let written = stream_field_to_file(&mut field, &dest, caps.scaler, FieldKind::Scaler).await?;
|
||||
scaler_summary = Some((scaler_filename, written));
|
||||
}
|
||||
other => {
|
||||
@ -306,9 +336,9 @@ async fn stream_field_to_file(
|
||||
total = total.saturating_add(chunk.len());
|
||||
if total > max_bytes {
|
||||
return Err(match kind {
|
||||
FieldKind::Manifest => UploadError::ManifestTooLarge,
|
||||
FieldKind::Onnx => UploadError::OnnxTooLarge,
|
||||
FieldKind::Scaler => UploadError::ScalerTooLarge,
|
||||
FieldKind::Manifest => UploadError::ManifestTooLarge(max_bytes),
|
||||
FieldKind::Onnx => UploadError::OnnxTooLarge(max_bytes),
|
||||
FieldKind::Scaler => UploadError::ScalerTooLarge(max_bytes),
|
||||
});
|
||||
}
|
||||
file.write_all(&chunk)
|
||||
@ -483,13 +513,13 @@ async fn validate_and_promote(
|
||||
"adapter_kind": manifest.adapter.as_str(),
|
||||
"manifest_sha256": manifest_sha256,
|
||||
"onnx_sha256": onnx_sha256,
|
||||
"before": serde_json::to_value(&before_status).unwrap_or(serde_json::Value::Null),
|
||||
"before": serde_json::to_value(&before_status).unwrap_or(JsonValue::Null),
|
||||
})
|
||||
.to_string();
|
||||
let _ = comm
|
||||
.publish_event(AuditEvent {
|
||||
actor: format!("SecurityAdmin@{actor_username}"),
|
||||
action: "model_swap".to_string(),
|
||||
actor: format!("{AUDIT_ACTOR_SECURITY_ADMIN_PREFIX}@{actor_username}"),
|
||||
action: AUDIT_ACTION_MODEL_SWAP.to_string(),
|
||||
detail: audit_detail,
|
||||
})
|
||||
.await;
|
||||
@ -549,10 +579,10 @@ impl PromoteError {
|
||||
/// Read `path` in 64KB chunks and return its SHA-256 hex digest.
|
||||
/// Offloaded to `spawn_blocking` so a large ONNX can't stall the
|
||||
/// actix worker while the hash computes.
|
||||
async fn sha256_file(path: &Path) -> std::io::Result<String> {
|
||||
async fn sha256_file(path: &Path) -> io::Result<String> {
|
||||
let path = path.to_path_buf();
|
||||
tokio::task::spawn_blocking(move || -> std::io::Result<String> {
|
||||
let mut file = std::fs::File::open(&path)?;
|
||||
task::spawn_blocking(move || -> io::Result<String> {
|
||||
let mut file = StdFile::open(&path)?;
|
||||
let mut hasher = Sha256::new();
|
||||
let mut buf = [0u8; 64 * 1024];
|
||||
loop {
|
||||
@ -572,18 +602,18 @@ async fn sha256_file(path: &Path) -> std::io::Result<String> {
|
||||
Ok(hex)
|
||||
})
|
||||
.await
|
||||
.unwrap_or_else(|e| Err(std::io::Error::other(format!("sha256 join: {e}"))))
|
||||
.unwrap_or_else(|e| Err(io::Error::other(format!("sha256 join: {e}"))))
|
||||
}
|
||||
|
||||
/// Remove staging subdirectories older than `max_age`. Runs on startup
|
||||
/// and on a periodic timer so failed uploads don't accumulate.
|
||||
pub fn clean_staging_orphans(staging_root: &Path, max_age: std::time::Duration) -> std::io::Result<usize> {
|
||||
pub fn clean_staging_orphans(staging_root: &Path, max_age: Duration) -> io::Result<usize> {
|
||||
if !staging_root.exists() {
|
||||
return Ok(0);
|
||||
}
|
||||
let now = std::time::SystemTime::now();
|
||||
let now = SystemTime::now();
|
||||
let mut cleaned = 0usize;
|
||||
for entry in std::fs::read_dir(staging_root)? {
|
||||
for entry in std_fs::read_dir(staging_root)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
if !path.is_dir() {
|
||||
@ -593,7 +623,7 @@ pub fn clean_staging_orphans(staging_root: &Path, max_age: std::time::Duration)
|
||||
let mtime = metadata.modified()?;
|
||||
let age = now.duration_since(mtime).unwrap_or_default();
|
||||
if age >= max_age {
|
||||
std::fs::remove_dir_all(&path)?;
|
||||
std_fs::remove_dir_all(&path)?;
|
||||
cleaned += 1;
|
||||
}
|
||||
}
|
||||
@ -754,8 +784,20 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upload_error_scaler_too_large_maps_to_413() {
|
||||
let resp = UploadError::ScalerTooLarge.into_response();
|
||||
fn upload_error_scaler_too_large_maps_to_413_and_echoes_cap() {
|
||||
let resp = UploadError::ScalerTooLarge(1234).into_response();
|
||||
assert_eq!(resp.status().as_u16(), 413);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn upload_error_onnx_too_large_echoes_configured_cap_in_message() {
|
||||
// Dynamic cap from config must reach the client verbatim — this
|
||||
// guards against a future refactor that silently drops the cap
|
||||
// from the format string.
|
||||
let rendered = format!("{:?}", UploadError::OnnxTooLarge(7_000_000));
|
||||
assert!(
|
||||
rendered.contains("7000000"),
|
||||
"rendered error must include the cap: {rendered}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -67,11 +67,7 @@ pub async fn flow_stats_ws(
|
||||
}
|
||||
}
|
||||
}
|
||||
Some(Ok(Message::Ping(bytes))) => {
|
||||
if session.pong(&bytes).await.is_err() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Some(Ok(Message::Ping(bytes))) if session.pong(&bytes).await.is_err() => break,
|
||||
Some(Ok(Message::Close(_))) | None => break,
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
//! recording stopped, not just a tracing line that may be lost.
|
||||
//! Callers see the channel disconnect and stop sending rows.
|
||||
|
||||
use std::fs as std_fs;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, BufWriter, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -50,6 +51,16 @@ pub const FLOW_TRACE_FILE_MARKER: &str = "flow-trace-";
|
||||
/// Suffix literal appended to every rotated file.
|
||||
pub const FLOW_TRACE_FILE_EXT: &str = ".csv";
|
||||
|
||||
/// Actor recorded on the WORM `flow_trace_stopped` audit entry. Stable
|
||||
/// wire string — auditors filter on it to separate system-internal
|
||||
/// recording stoppages from administrator-initiated actions. Matches
|
||||
/// the "system" value the drift-detector audit path already uses.
|
||||
const AUDIT_ACTOR_SYSTEM: &str = "system";
|
||||
/// Action string on the WORM audit entry emitted when Flow Trace
|
||||
/// recording goes dormant for any of the three writer-thread stop
|
||||
/// reasons. Stable across releases.
|
||||
const AUDIT_ACTION_FLOW_TRACE_STOPPED: &str = "flow_trace_stopped";
|
||||
|
||||
/// Rotation thresholds. Immutable after logger construction — change
|
||||
/// requires a full logger restart through `AppServices`.
|
||||
#[derive(Debug, Clone)]
|
||||
@ -90,7 +101,7 @@ impl TrafficLogger {
|
||||
.parent()
|
||||
.map(Path::to_path_buf)
|
||||
.unwrap_or_else(|| PathBuf::from("."));
|
||||
std::fs::create_dir_all(&directory)?;
|
||||
std_fs::create_dir_all(&directory)?;
|
||||
|
||||
let (sender, receiver) = bounded::<Vec<String>>(CHANNEL_CAPACITY);
|
||||
|
||||
@ -150,7 +161,7 @@ pub fn list_flow_trace_files(directory: &Path) -> io::Result<Vec<FlowTraceFile>>
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let mut entries = Vec::new();
|
||||
for dirent in std::fs::read_dir(directory)? {
|
||||
for dirent in std_fs::read_dir(directory)? {
|
||||
let dirent = dirent?;
|
||||
let path = dirent.path();
|
||||
if !path.is_file() {
|
||||
@ -265,8 +276,8 @@ fn emit_flow_trace_stop_audit(comm: Option<&Arc<CommunicationManager>>, reason:
|
||||
})
|
||||
.to_string();
|
||||
let _ = c.publish_event_sync(AuditEvent {
|
||||
actor: "system".to_string(),
|
||||
action: "flow_trace_stopped".to_string(),
|
||||
actor: AUDIT_ACTOR_SYSTEM.to_string(),
|
||||
action: AUDIT_ACTION_FLOW_TRACE_STOPPED.to_string(),
|
||||
detail,
|
||||
});
|
||||
}
|
||||
@ -310,7 +321,7 @@ pub fn enforce_fifo_budget(directory: &Path, budget: u64) -> io::Result<()> {
|
||||
if remaining <= budget {
|
||||
break;
|
||||
}
|
||||
std::fs::remove_file(&file.path)?;
|
||||
std_fs::remove_file(&file.path)?;
|
||||
remaining = remaining.saturating_sub(file.size_bytes);
|
||||
}
|
||||
Ok(())
|
||||
@ -318,6 +329,7 @@ pub fn enforce_fifo_budget(directory: &Path, budget: u64) -> io::Result<()> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::env;
|
||||
use std::io::Write as _;
|
||||
|
||||
use uuid::Uuid;
|
||||
@ -325,14 +337,14 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
fn scratch_dir(tag: &str) -> PathBuf {
|
||||
let dir = std::env::temp_dir().join(format!("nguardia-flow-trace-{tag}-{}", Uuid::new_v4()));
|
||||
std::fs::create_dir_all(&dir).unwrap();
|
||||
let dir = env::temp_dir().join(format!("nguardia-flow-trace-{tag}-{}", Uuid::new_v4()));
|
||||
std_fs::create_dir_all(&dir).unwrap();
|
||||
dir
|
||||
}
|
||||
|
||||
fn write_fake_trace(dir: &Path, ts_ns: u64, bytes: usize) -> PathBuf {
|
||||
let path = dir.join(format!("{FLOW_TRACE_FILE_MARKER}{ts_ns:020}{FLOW_TRACE_FILE_EXT}"));
|
||||
let mut f = std::fs::File::create(&path).unwrap();
|
||||
let mut f = File::create(&path).unwrap();
|
||||
f.write_all(&vec![b'a'; bytes]).unwrap();
|
||||
path
|
||||
}
|
||||
|
||||
@ -58,6 +58,18 @@ impl AppConfig {
|
||||
("inference_batch_size", "200".into()),
|
||||
("traffic_logging_mode", "false".into()),
|
||||
("traffic_log_csv_path", "traffic_log.csv".into()),
|
||||
// Flow Trace rotation (defaults match the DEFAULT_* constants
|
||||
// in traffic_logger.rs; DB overrides let admins tune per env).
|
||||
("flow_trace_max_file_bytes", (500 * 1024 * 1024_u64).to_string()),
|
||||
("flow_trace_max_file_age_secs", "3600".into()),
|
||||
(
|
||||
"flow_trace_total_budget_bytes",
|
||||
(10 * 1024 * 1024 * 1024_u64).to_string(),
|
||||
),
|
||||
// Model upload size caps (per-field multipart ceilings).
|
||||
("model_upload_max_onnx_bytes", (100 * 1024 * 1024_usize).to_string()),
|
||||
("model_upload_max_manifest_bytes", (64 * 1024_usize).to_string()),
|
||||
("model_upload_max_scaler_bytes", (64 * 1024_usize).to_string()),
|
||||
// Misc
|
||||
("geoip_db_name", "net-guardia/static/geo/dbip-city-lite.mmdb".into()),
|
||||
// Pipeline
|
||||
@ -131,6 +143,12 @@ impl AppConfig {
|
||||
inference_batch_size: 200,
|
||||
traffic_logging_mode: false,
|
||||
traffic_log_csv_path: "traffic_log.csv".into(),
|
||||
flow_trace_max_file_bytes: 500 * 1024 * 1024,
|
||||
flow_trace_max_file_age_secs: 3600,
|
||||
flow_trace_total_budget_bytes: 10 * 1024 * 1024 * 1024,
|
||||
model_upload_max_onnx_bytes: 100 * 1024 * 1024,
|
||||
model_upload_max_manifest_bytes: 64 * 1024,
|
||||
model_upload_max_scaler_bytes: 64 * 1024,
|
||||
},
|
||||
misc: MiscConfig {
|
||||
geoip_db_name: "net-guardia/static/geo/dbip-city-lite.mmdb".into(),
|
||||
@ -244,6 +262,36 @@ impl AppConfig {
|
||||
{
|
||||
config.inference.inference_batch_size = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("flow_trace_max_file_bytes")
|
||||
&& let Ok(n) = v.parse::<u64>()
|
||||
{
|
||||
config.inference.flow_trace_max_file_bytes = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("flow_trace_max_file_age_secs")
|
||||
&& let Ok(n) = v.parse::<u64>()
|
||||
{
|
||||
config.inference.flow_trace_max_file_age_secs = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("flow_trace_total_budget_bytes")
|
||||
&& let Ok(n) = v.parse::<u64>()
|
||||
{
|
||||
config.inference.flow_trace_total_budget_bytes = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("model_upload_max_onnx_bytes")
|
||||
&& let Ok(n) = v.parse::<usize>()
|
||||
{
|
||||
config.inference.model_upload_max_onnx_bytes = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("model_upload_max_manifest_bytes")
|
||||
&& let Ok(n) = v.parse::<usize>()
|
||||
{
|
||||
config.inference.model_upload_max_manifest_bytes = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("model_upload_max_scaler_bytes")
|
||||
&& let Ok(n) = v.parse::<usize>()
|
||||
{
|
||||
config.inference.model_upload_max_scaler_bytes = n;
|
||||
}
|
||||
if let Ok(Some(v)) = db.get_setting("refresh_interval")
|
||||
&& let Ok(n) = v.parse::<u64>()
|
||||
{
|
||||
|
||||
@ -103,7 +103,12 @@ impl AppServices {
|
||||
let mut header = FlowFeatures::all_feature_names_owned();
|
||||
header.push("Label".to_string());
|
||||
let base_path = PathBuf::from(&csv_path);
|
||||
let logger = TrafficLogger::new(&base_path, header, RotationPolicy::default(), Some(comm.clone()))
|
||||
let policy = RotationPolicy {
|
||||
max_file_bytes: app_config.inference.flow_trace_max_file_bytes,
|
||||
max_file_age: Duration::from_secs(app_config.inference.flow_trace_max_file_age_secs),
|
||||
total_budget_bytes: app_config.inference.flow_trace_total_budget_bytes,
|
||||
};
|
||||
let logger = TrafficLogger::new(&base_path, header, policy, Some(comm.clone()))
|
||||
.map_err(|e| MiscError::TrafficLogCreateError(csv_path.clone(), e.to_string()))?;
|
||||
log!(SystemLog::TrafficLoggingEnabled(csv_path));
|
||||
Some(Arc::new(logger))
|
||||
|
||||
@ -110,7 +110,7 @@ impl SecretStore {
|
||||
.ok_or_else(|| CryptoError::MissingEnvelopeField("nonce"))?;
|
||||
|
||||
let nonce_bytes = B64.decode(nonce_b64).map_err(CryptoError::DecryptionFailed)?;
|
||||
let nonce = Nonce::from_exact_iter(nonce_bytes.into_iter()).ok_or(CryptoError::InvalidNonceLength)?;
|
||||
let nonce = Nonce::from_exact_iter(nonce_bytes).ok_or(CryptoError::InvalidNonceLength)?;
|
||||
|
||||
let ciphertext = B64.decode(ct_b64).map_err(CryptoError::DecryptionFailed)?;
|
||||
|
||||
|
||||
@ -65,7 +65,7 @@ impl FlowStatistics {
|
||||
flows.retain(|f| f.last_seen_us >= cutoff);
|
||||
}
|
||||
|
||||
flows.sort_by(|a, b| (b.fwd_bytes + b.bwd_bytes).cmp(&(a.fwd_bytes + a.bwd_bytes)));
|
||||
flows.sort_by_key(|f| std::cmp::Reverse(f.fwd_bytes + f.bwd_bytes));
|
||||
|
||||
if let Some(n) = sub.top_n {
|
||||
flows.truncate(n.min(10000));
|
||||
|
||||
@ -14,7 +14,6 @@ pub struct Playbook {
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PlaybookAction {
|
||||
#[allow(dead_code)] // Kept for domain completeness; ordering handled by SQL ORDER BY
|
||||
pub action_order: i64,
|
||||
pub action_type: String,
|
||||
pub params: serde_json::Value,
|
||||
|
||||
@ -56,6 +56,58 @@ pub struct InferenceConfig {
|
||||
pub inference_batch_size: usize,
|
||||
pub traffic_logging_mode: bool,
|
||||
pub traffic_log_csv_path: String,
|
||||
/// Rotation: close the current CSV when it reaches this many bytes
|
||||
/// and open a fresh one. 500MB default — large enough that dropdown
|
||||
/// analysis tools can eat a shard in one gulp, small enough that
|
||||
/// a browser download finishes in reasonable time.
|
||||
#[serde(default = "default_flow_trace_max_file_bytes")]
|
||||
pub flow_trace_max_file_bytes: u64,
|
||||
/// Rotation: also roll when the active file crosses this age in
|
||||
/// seconds, so analysts always have bounded-age shards regardless
|
||||
/// of traffic volume. 1h default.
|
||||
#[serde(default = "default_flow_trace_max_file_age_secs")]
|
||||
pub flow_trace_max_file_age_secs: u64,
|
||||
/// FIFO budget: total bytes across every rotated shard in the
|
||||
/// directory. When exceeded, oldest files are deleted until the
|
||||
/// sum is back under budget. 10GB default keeps a few days of
|
||||
/// recording on a typical office link.
|
||||
#[serde(default = "default_flow_trace_total_budget_bytes")]
|
||||
pub flow_trace_total_budget_bytes: u64,
|
||||
/// Hard ceiling on the multipart `.onnx` stream. 100MB default fits
|
||||
/// every shipped shape of netguardia's own model plus headroom for
|
||||
/// medium BYO networks; very large models (modern transformers)
|
||||
/// can raise this, at the cost of a wider DoS surface.
|
||||
#[serde(default = "default_model_upload_max_onnx_bytes")]
|
||||
pub model_upload_max_onnx_bytes: usize,
|
||||
/// Hard ceiling on the multipart `manifest` YAML stream. 64KB
|
||||
/// default is ~100× the largest realistic manifest.
|
||||
#[serde(default = "default_model_upload_max_manifest_bytes")]
|
||||
pub model_upload_max_manifest_bytes: usize,
|
||||
/// Hard ceiling on the optional `scaler` JSON sidecar stream.
|
||||
/// Shares the 64KB default with the manifest cap — sidecars are
|
||||
/// numeric arrays whose size scales with feature count, so even a
|
||||
/// generous feature set stays well under.
|
||||
#[serde(default = "default_model_upload_max_scaler_bytes")]
|
||||
pub model_upload_max_scaler_bytes: usize,
|
||||
}
|
||||
|
||||
fn default_flow_trace_max_file_bytes() -> u64 {
|
||||
500 * 1024 * 1024
|
||||
}
|
||||
fn default_flow_trace_max_file_age_secs() -> u64 {
|
||||
3600
|
||||
}
|
||||
fn default_flow_trace_total_budget_bytes() -> u64 {
|
||||
10 * 1024 * 1024 * 1024
|
||||
}
|
||||
fn default_model_upload_max_onnx_bytes() -> usize {
|
||||
100 * 1024 * 1024
|
||||
}
|
||||
fn default_model_upload_max_manifest_bytes() -> usize {
|
||||
64 * 1024
|
||||
}
|
||||
fn default_model_upload_max_scaler_bytes() -> usize {
|
||||
64 * 1024
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||
|
||||
3
rust-toolchain.toml
Normal file
3
rust-toolchain.toml
Normal file
@ -0,0 +1,3 @@
|
||||
[toolchain]
|
||||
channel = "1.95.0"
|
||||
components = ["clippy", "rustfmt"]
|
||||
Loading…
x
Reference in New Issue
Block a user