diff --git a/Cargo.lock b/Cargo.lock
index e914ef143..85117faab 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -521,6 +521,22 @@ dependencies = [
"zbus",
]
+[[package]]
+name = "astral-tokio-tar"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec179a06c1769b1e42e1e2cbe74c7dcdb3d6383c838454d063eaac5bbb7ebbe5"
+dependencies = [
+ "filetime",
+ "futures-core",
+ "libc",
+ "portable-atomic",
+ "rustc-hash",
+ "tokio",
+ "tokio-stream",
+ "xattr",
+]
+
[[package]]
name = "async-broadcast"
version = "0.7.2"
@@ -671,6 +687,28 @@ dependencies = [
"windows-sys 0.61.2",
]
+[[package]]
+name = "async-stream"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
+dependencies = [
+ "async-stream-impl",
+ "futures-core",
+ "pin-project-lite",
+]
+
+[[package]]
+name = "async-stream-impl"
+version = "0.3.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
[[package]]
name = "async-stripe"
version = "0.41.0"
@@ -892,6 +930,49 @@ dependencies = [
"thiserror 2.0.17",
]
+[[package]]
+name = "axum"
+version = "0.8.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8"
+dependencies = [
+ "axum-core",
+ "bytes",
+ "futures-util",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "itoa",
+ "matchit",
+ "memchr",
+ "mime",
+ "percent-encoding",
+ "pin-project-lite",
+ "serde_core",
+ "sync_wrapper",
+ "tower",
+ "tower-layer",
+ "tower-service",
+]
+
+[[package]]
+name = "axum-core"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1"
+dependencies = [
+ "bytes",
+ "futures-core",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "mime",
+ "pin-project-lite",
+ "sync_wrapper",
+ "tower-layer",
+ "tower-service",
+]
+
[[package]]
name = "backtrace"
version = "0.3.76"
@@ -1066,6 +1147,83 @@ dependencies = [
"piper",
]
+[[package]]
+name = "bollard"
+version = "0.19.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "87a52479c9237eb04047ddb94788c41ca0d26eaff8b697ecfbb4c32f7fdc3b1b"
+dependencies = [
+ "async-stream",
+ "base64 0.22.1",
+ "bitflags 2.9.4",
+ "bollard-buildkit-proto",
+ "bollard-stubs",
+ "bytes",
+ "chrono",
+ "futures-core",
+ "futures-util",
+ "hex",
+ "home",
+ "http 1.3.1",
+ "http-body-util",
+ "hyper 1.7.0",
+ "hyper-named-pipe",
+ "hyper-rustls 0.27.7",
+ "hyper-util",
+ "hyperlocal",
+ "log",
+ "num",
+ "pin-project-lite",
+ "rand 0.9.2",
+ "rustls 0.23.32",
+ "rustls-native-certs 0.8.1",
+ "rustls-pemfile 2.2.0",
+ "rustls-pki-types",
+ "serde",
+ "serde_derive",
+ "serde_json",
+ "serde_repr",
+ "serde_urlencoded",
+ "thiserror 2.0.17",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "tonic 0.14.2",
+ "tower-service",
+ "url",
+ "winapi",
+]
+
+[[package]]
+name = "bollard-buildkit-proto"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "85a885520bf6249ab931a764ffdb87b0ceef48e6e7d807cfdb21b751e086e1ad"
+dependencies = [
+ "prost 0.14.3",
+ "prost-types",
+ "tonic 0.14.2",
+ "tonic-prost",
+ "ureq",
+]
+
+[[package]]
+name = "bollard-stubs"
+version = "1.49.1-rc.28.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5731fe885755e92beff1950774068e0cae67ea6ec7587381536fca84f1779623"
+dependencies = [
+ "base64 0.22.1",
+ "bollard-buildkit-proto",
+ "bytes",
+ "chrono",
+ "prost 0.14.3",
+ "serde",
+ "serde_json",
+ "serde_repr",
+ "serde_with",
+]
+
[[package]]
name = "borsh"
version = "1.5.7"
@@ -2378,6 +2536,17 @@ dependencies = [
"const-random",
]
+[[package]]
+name = "docker_credential"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1d89dfcba45b4afad7450a99b39e751590463e45c04728cf555d36bb66940de8"
+dependencies = [
+ "base64 0.21.7",
+ "serde",
+ "serde_json",
+]
+
[[package]]
name = "document-features"
version = "0.2.11"
@@ -2679,6 +2848,17 @@ dependencies = [
"windows-sys 0.48.0",
]
+[[package]]
+name = "etcetera"
+version = "0.10.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26c7b13d0780cb82722fd59f6f57f925e143427e4a75313a6c77243bf5326ae6"
+dependencies = [
+ "cfg-if",
+ "home",
+ "windows-sys 0.59.0",
+]
+
[[package]]
name = "event-listener"
version = "2.5.3"
@@ -3801,6 +3981,21 @@ dependencies = [
"want",
]
+[[package]]
+name = "hyper-named-pipe"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "73b7d8abf35697b81a825e386fc151e0d503e8cb5fcb93cc8669c376dfd6f278"
+dependencies = [
+ "hex",
+ "hyper 1.7.0",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+ "winapi",
+]
+
[[package]]
name = "hyper-rustls"
version = "0.24.2"
@@ -3835,6 +4030,19 @@ dependencies = [
"webpki-roots 1.0.3",
]
+[[package]]
+name = "hyper-timeout"
+version = "0.5.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
+dependencies = [
+ "hyper 1.7.0",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
[[package]]
name = "hyper-tls"
version = "0.6.0"
@@ -3877,6 +4085,21 @@ dependencies = [
"windows-registry",
]
+[[package]]
+name = "hyperlocal"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "986c5ce3b994526b3cd75578e62554abd09f0899d6206de48b3e96ab34ccc8c7"
+dependencies = [
+ "hex",
+ "http-body-util",
+ "hyper 1.7.0",
+ "hyper-util",
+ "pin-project-lite",
+ "tokio",
+ "tower-service",
+]
+
[[package]]
name = "iana-time-zone"
version = "0.1.64"
@@ -4566,6 +4789,7 @@ dependencies = [
"sha2",
"spdx",
"sqlx",
+ "sqlx-tracing",
"strum",
"thiserror 2.0.17",
"tikv-jemalloc-ctl",
@@ -4888,6 +5112,12 @@ version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5"
+[[package]]
+name = "matchit"
+version = "0.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
+
[[package]]
name = "maxminddb"
version = "0.26.0"
@@ -5873,6 +6103,124 @@ dependencies = [
"vcpkg",
]
+[[package]]
+name = "opentelemetry"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aaf416e4cb72756655126f7dd7bb0af49c674f4c1b9903e80c009e0c37e552e6"
+dependencies = [
+ "futures-core",
+ "futures-sink",
+ "js-sys",
+ "pin-project-lite",
+ "thiserror 2.0.17",
+ "tracing",
+]
+
+[[package]]
+name = "opentelemetry-appender-tracing"
+version = "0.30.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e68f63eca5fad47e570e00e893094fc17be959c80c79a7d6ec1abdd5ae6ffc16"
+dependencies = [
+ "opentelemetry",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+ "tracing-opentelemetry",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "opentelemetry-http"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d"
+dependencies = [
+ "async-trait",
+ "bytes",
+ "http 1.3.1",
+ "opentelemetry",
+ "reqwest",
+]
+
+[[package]]
+name = "opentelemetry-otlp"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b"
+dependencies = [
+ "http 1.3.1",
+ "opentelemetry",
+ "opentelemetry-http",
+ "opentelemetry-proto",
+ "opentelemetry_sdk",
+ "prost 0.13.5",
+ "reqwest",
+ "thiserror 2.0.17",
+ "tokio",
+ "tonic 0.13.1",
+ "tracing",
+]
+
+[[package]]
+name = "opentelemetry-proto"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2e046fd7660710fe5a05e8748e70d9058dc15c94ba914e7c4faa7c728f0e8ddc"
+dependencies = [
+ "opentelemetry",
+ "opentelemetry_sdk",
+ "prost 0.13.5",
+ "tonic 0.13.1",
+]
+
+[[package]]
+name = "opentelemetry-semantic-conventions"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "83d059a296a47436748557a353c5e6c5705b9470ef6c95cfc52c21a8814ddac2"
+
+[[package]]
+name = "opentelemetry-testing"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "562407eb254fea88076c8a410a733a8ee2075fd9c7fbde3da2a03d29e2cef104"
+dependencies = [
+ "anyhow",
+ "opentelemetry",
+ "opentelemetry-appender-tracing",
+ "opentelemetry-otlp",
+ "opentelemetry-semantic-conventions",
+ "opentelemetry_sdk",
+ "serde",
+ "serde_json",
+ "serial_test",
+ "tempfile",
+ "testcontainers",
+ "tokio",
+ "tracing-opentelemetry",
+ "tracing-subscriber",
+]
+
+[[package]]
+name = "opentelemetry_sdk"
+version = "0.30.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11f644aa9e5e31d11896e024305d7e3c98a88884d9f8919dbf37a9991bc47a4b"
+dependencies = [
+ "futures-channel",
+ "futures-executor",
+ "futures-util",
+ "opentelemetry",
+ "percent-encoding",
+ "rand 0.9.2",
+ "serde_json",
+ "thiserror 2.0.17",
+ "tokio",
+ "tokio-stream",
+]
+
[[package]]
name = "option-ext"
version = "0.2.0"
@@ -5997,6 +6345,31 @@ dependencies = [
"windows-link 0.2.1",
]
+[[package]]
+name = "parse-display"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "914a1c2265c98e2446911282c6ac86d8524f495792c38c5bd884f80499c7538a"
+dependencies = [
+ "parse-display-derive",
+ "regex",
+ "regex-syntax",
+]
+
+[[package]]
+name = "parse-display-derive"
+version = "0.9.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ae7800a4c974efd12df917266338e79a7a74415173caf7e70aa0a0707345281"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "regex",
+ "regex-syntax",
+ "structmeta",
+ "syn 2.0.106",
+]
+
[[package]]
name = "parse-size"
version = "1.1.0"
@@ -6384,7 +6757,7 @@ dependencies = [
"inferno",
"num",
"paste",
- "prost",
+ "prost 0.13.5",
]
[[package]]
@@ -6590,7 +6963,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
dependencies = [
"bytes",
- "prost-derive",
+ "prost-derive 0.13.5",
+]
+
+[[package]]
+name = "prost"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568"
+dependencies = [
+ "bytes",
+ "prost-derive 0.14.3",
]
[[package]]
@@ -6606,6 +6989,28 @@ dependencies = [
"syn 2.0.106",
]
+[[package]]
+name = "prost-derive"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b"
+dependencies = [
+ "anyhow",
+ "itertools 0.14.0",
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
+[[package]]
+name = "prost-types"
+version = "0.14.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7"
+dependencies = [
+ "prost 0.14.3",
+]
+
[[package]]
name = "protobuf"
version = "3.7.2"
@@ -7633,6 +8038,15 @@ dependencies = [
"winapi-util",
]
+[[package]]
+name = "scc"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46e6f046b7fef48e2660c57ed794263155d713de679057f2d0c169bfc6e756cc"
+dependencies = [
+ "sdd",
+]
+
[[package]]
name = "schannel"
version = "0.1.28"
@@ -7724,6 +8138,12 @@ dependencies = [
"untrusted",
]
+[[package]]
+name = "sdd"
+version = "3.0.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "490dcfcbfef26be6800d11870ff2df8774fa6e86d047e3e8c8a76b25655e41ca"
+
[[package]]
name = "seahash"
version = "4.1.0"
@@ -8170,6 +8590,32 @@ dependencies = [
"syn 2.0.106",
]
+[[package]]
+name = "serial_test"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0d0b343e184fc3b7bb44dff0705fffcf4b3756ba6aff420dddd8b24ca145e555"
+dependencies = [
+ "futures-executor",
+ "futures-util",
+ "log",
+ "once_cell",
+ "parking_lot",
+ "scc",
+ "serial_test_derive",
+]
+
+[[package]]
+name = "serial_test_derive"
+version = "3.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6f50427f258fb77356e4cd4aa0e87e2bd2c66dbcee41dc405282cae2bfc26c83"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.106",
+]
+
[[package]]
name = "serialize-to-javascript"
version = "0.1.2"
@@ -8576,7 +9022,7 @@ dependencies = [
"chrono",
"crc",
"dotenvy",
- "etcetera",
+ "etcetera 0.8.0",
"futures-channel",
"futures-core",
"futures-util",
@@ -8629,6 +9075,20 @@ dependencies = [
"uuid 1.18.1",
]
+[[package]]
+name = "sqlx-tracing"
+version = "0.2.0"
+dependencies = [
+ "derive_more 2.0.1",
+ "futures",
+ "opentelemetry",
+ "opentelemetry-testing",
+ "sqlx",
+ "testcontainers",
+ "tokio",
+ "tracing",
+]
+
[[package]]
name = "stable_deref_trait"
version = "1.2.1"
@@ -9405,6 +9865,35 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "testcontainers"
+version = "0.25.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f3ac71069f20ecfa60c396316c283fbf35e6833a53dff551a31b5458da05edc"
+dependencies = [
+ "astral-tokio-tar",
+ "async-trait",
+ "bollard",
+ "bytes",
+ "docker_credential",
+ "either",
+ "etcetera 0.10.0",
+ "futures",
+ "log",
+ "memchr",
+ "parse-display",
+ "pin-project-lite",
+ "serde",
+ "serde_json",
+ "serde_with",
+ "thiserror 2.0.17",
+ "tokio",
+ "tokio-stream",
+ "tokio-util",
+ "ulid",
+ "url",
+]
+
[[package]]
name = "theseus"
version = "1.0.0-local"
@@ -9871,6 +10360,72 @@ version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df8b2b54733674ad286d16267dcfc7a71ed5c776e4ac7aa3c3e2561f7c637bf2"
+[[package]]
+name = "tonic"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e581ba15a835f4d9ea06c55ab1bd4dce26fc53752c69a04aac00703bfb49ba9"
+dependencies = [
+ "async-trait",
+ "base64 0.22.1",
+ "bytes",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "hyper 1.7.0",
+ "hyper-timeout",
+ "hyper-util",
+ "percent-encoding",
+ "pin-project",
+ "prost 0.13.5",
+ "tokio",
+ "tokio-stream",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tonic"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb7613188ce9f7df5bfe185db26c5814347d110db17920415cf2fbcad85e7203"
+dependencies = [
+ "async-trait",
+ "axum",
+ "base64 0.22.1",
+ "bytes",
+ "h2 0.4.12",
+ "http 1.3.1",
+ "http-body 1.0.1",
+ "http-body-util",
+ "hyper 1.7.0",
+ "hyper-timeout",
+ "hyper-util",
+ "percent-encoding",
+ "pin-project",
+ "socket2 0.6.1",
+ "sync_wrapper",
+ "tokio",
+ "tokio-stream",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
+]
+
+[[package]]
+name = "tonic-prost"
+version = "0.14.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
+dependencies = [
+ "bytes",
+ "prost 0.14.3",
+ "tonic 0.14.2",
+]
+
[[package]]
name = "totp-rs"
version = "5.7.0"
@@ -9893,11 +10448,15 @@ checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
dependencies = [
"futures-core",
"futures-util",
+ "indexmap 2.11.4",
"pin-project-lite",
+ "slab",
"sync_wrapper",
"tokio",
+ "tokio-util",
"tower-layer",
"tower-service",
+ "tracing",
]
[[package]]
@@ -10013,6 +10572,24 @@ dependencies = [
"tracing-core",
]
+[[package]]
+name = "tracing-opentelemetry"
+version = "0.31.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ddcf5959f39507d0d04d6413119c04f33b623f4f951ebcbdddddfad2d0623a9c"
+dependencies = [
+ "js-sys",
+ "once_cell",
+ "opentelemetry",
+ "opentelemetry_sdk",
+ "smallvec",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
+ "tracing-subscriber",
+ "web-time",
+]
+
[[package]]
name = "tracing-subscriber"
version = "0.3.20"
@@ -10108,6 +10685,16 @@ dependencies = [
"winapi",
]
+[[package]]
+name = "ulid"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe"
+dependencies = [
+ "rand 0.9.2",
+ "web-time",
+]
+
[[package]]
name = "uname"
version = "0.1.1"
diff --git a/Cargo.toml b/Cargo.toml
index 4d8fbcc54..5b52543f6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -164,6 +164,7 @@ sha2 = "0.10.9"
shlex = "1.3.0"
spdx = "0.12.0"
sqlx = { version = "0.8.6", default-features = false }
+sqlx-tracing = { path = "packages/sqlx-tracing" }
strum = "0.27.2"
sysinfo = { version = "0.37.2", default-features = false }
tar = "0.4.44"
@@ -269,4 +270,5 @@ codegen-units = 1 # Compile crates one after another so the compiler can optimi
# Specific profile for labrinth production builds
[profile.release-labrinth]
inherits = "release"
+strip = false # Keep debug symbols for Sentry
panic = "unwind" # Don't exit the whole app on panic in production
diff --git a/apps/labrinth/.sqlx/query-1adbd24d815107e13bc1440c7a8f4eeff66ab4165a9f4980032e114db4dc1286.json b/apps/labrinth/.sqlx/query-1adbd24d815107e13bc1440c7a8f4eeff66ab4165a9f4980032e114db4dc1286.json
new file mode 100644
index 000000000..921f7f92d
--- /dev/null
+++ b/apps/labrinth/.sqlx/query-1adbd24d815107e13bc1440c7a8f4eeff66ab4165a9f4980032e114db4dc1286.json
@@ -0,0 +1,26 @@
+{
+ "db_name": "PostgreSQL",
+ "query": "\n SELECT\n id,\n status AS \"status: PayoutStatus\"\n FROM payouts\n ORDER BY id\n ",
+ "describe": {
+ "columns": [
+ {
+ "ordinal": 0,
+ "name": "id",
+ "type_info": "Int8"
+ },
+ {
+ "ordinal": 1,
+ "name": "status: PayoutStatus",
+ "type_info": "Varchar"
+ }
+ ],
+ "parameters": {
+ "Left": []
+ },
+ "nullable": [
+ false,
+ false
+ ]
+ },
+ "hash": "1adbd24d815107e13bc1440c7a8f4eeff66ab4165a9f4980032e114db4dc1286"
+}
diff --git a/apps/labrinth/.sqlx/query-79c73369365ed7a09f4f48a87605d22db4a49ab5fd9943b54865448d0e9a8d67.json b/apps/labrinth/.sqlx/query-ad48051c9ac8f233ebfeeebec834ff96df8525a6ed872be7a64b8f349b36b276.json
similarity index 68%
rename from apps/labrinth/.sqlx/query-79c73369365ed7a09f4f48a87605d22db4a49ab5fd9943b54865448d0e9a8d67.json
rename to apps/labrinth/.sqlx/query-ad48051c9ac8f233ebfeeebec834ff96df8525a6ed872be7a64b8f349b36b276.json
index dd98633e5..99373fb6a 100644
--- a/apps/labrinth/.sqlx/query-79c73369365ed7a09f4f48a87605d22db4a49ab5fd9943b54865448d0e9a8d67.json
+++ b/apps/labrinth/.sqlx/query-ad48051c9ac8f233ebfeeebec834ff96df8525a6ed872be7a64b8f349b36b276.json
@@ -1,6 +1,6 @@
{
"db_name": "PostgreSQL",
- "query": "\n INSERT INTO loader_field_enum_values (enum_id, value, created, metadata)\n VALUES ($1, $2, COALESCE($3, timezone('utc', now())), $4)\n ON CONFLICT (enum_id, value) DO UPDATE\n SET metadata = jsonb_set(\n COALESCE(loader_field_enum_values.metadata, $4),\n '{type}', \n COALESCE($4->'type', loader_field_enum_values.metadata->'type')\n ),\n created = COALESCE($3, loader_field_enum_values.created)\n RETURNING id\n ",
+ "query": "\n INSERT INTO loader_field_enum_values (enum_id, value, created, metadata)\n VALUES ($1, $2, COALESCE($3, timezone('utc', now())), $4)\n ON CONFLICT (enum_id, value) DO UPDATE\n SET metadata = jsonb_set(\n COALESCE(loader_field_enum_values.metadata, $4),\n '{type}',\n COALESCE($4->'type', loader_field_enum_values.metadata->'type')\n ),\n created = COALESCE($3, loader_field_enum_values.created)\n RETURNING id\n ",
"describe": {
"columns": [
{
@@ -21,5 +21,5 @@
false
]
},
- "hash": "79c73369365ed7a09f4f48a87605d22db4a49ab5fd9943b54865448d0e9a8d67"
+ "hash": "ad48051c9ac8f233ebfeeebec834ff96df8525a6ed872be7a64b8f349b36b276"
}
diff --git a/apps/labrinth/.sqlx/query-b92b5bb7d179c4fcdbc45600ccfd2402f52fea71e27b08e7926fcc2a9e62c0f3.json b/apps/labrinth/.sqlx/query-b92b5bb7d179c4fcdbc45600ccfd2402f52fea71e27b08e7926fcc2a9e62c0f3.json
new file mode 100644
index 000000000..89bd8147d
--- /dev/null
+++ b/apps/labrinth/.sqlx/query-b92b5bb7d179c4fcdbc45600ccfd2402f52fea71e27b08e7926fcc2a9e62c0f3.json
@@ -0,0 +1,20 @@
+{
+ "db_name": "PostgreSQL",
+ "query": "SELECT status AS \"status: PayoutStatus\" FROM payouts WHERE id = 1",
+ "describe": {
+ "columns": [
+ {
+ "ordinal": 0,
+ "name": "status: PayoutStatus",
+ "type_info": "Varchar"
+ }
+ ],
+ "parameters": {
+ "Left": []
+ },
+ "nullable": [
+ false
+ ]
+ },
+ "hash": "b92b5bb7d179c4fcdbc45600ccfd2402f52fea71e27b08e7926fcc2a9e62c0f3"
+}
diff --git a/apps/labrinth/.sqlx/query-cd5ccd618fb3cc41646a6de86f9afedb074492b4ec7f2457c14113f5fd13aa02.json b/apps/labrinth/.sqlx/query-cd5ccd618fb3cc41646a6de86f9afedb074492b4ec7f2457c14113f5fd13aa02.json
new file mode 100644
index 000000000..469c30168
--- /dev/null
+++ b/apps/labrinth/.sqlx/query-cd5ccd618fb3cc41646a6de86f9afedb074492b4ec7f2457c14113f5fd13aa02.json
@@ -0,0 +1,18 @@
+{
+ "db_name": "PostgreSQL",
+ "query": "\n INSERT INTO payouts (id, method, platform_id, status, user_id, amount, created)\n VALUES ($1, $2, $3, $4, $5, 10.0, NOW())\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Left": [
+ "Int8",
+ "Text",
+ "Text",
+ "Varchar",
+ "Int8"
+ ]
+ },
+ "nullable": []
+ },
+ "hash": "cd5ccd618fb3cc41646a6de86f9afedb074492b4ec7f2457c14113f5fd13aa02"
+}
diff --git a/apps/labrinth/.sqlx/query-cec4240c7c848988b3dfd13e3f8e5c93783c7641b019fdb698a1ec0be1393606.json b/apps/labrinth/.sqlx/query-cec4240c7c848988b3dfd13e3f8e5c93783c7641b019fdb698a1ec0be1393606.json
new file mode 100644
index 000000000..52e020ebf
--- /dev/null
+++ b/apps/labrinth/.sqlx/query-cec4240c7c848988b3dfd13e3f8e5c93783c7641b019fdb698a1ec0be1393606.json
@@ -0,0 +1,17 @@
+{
+ "db_name": "PostgreSQL",
+ "query": "\n INSERT INTO payouts (id, method, platform_id, status, user_id, amount, created)\n VALUES ($1, $2, NULL, $3, $4, 10.00, NOW())\n ",
+ "describe": {
+ "columns": [],
+ "parameters": {
+ "Left": [
+ "Int8",
+ "Text",
+ "Varchar",
+ "Int8"
+ ]
+ },
+ "nullable": []
+ },
+ "hash": "cec4240c7c848988b3dfd13e3f8e5c93783c7641b019fdb698a1ec0be1393606"
+}
diff --git a/apps/labrinth/Cargo.toml b/apps/labrinth/Cargo.toml
index aa6bdb0b3..76cbff499 100644
--- a/apps/labrinth/Cargo.toml
+++ b/apps/labrinth/Cargo.toml
@@ -27,7 +27,6 @@ async-stripe = { workspace = true, features = [
"connect",
"webhook-events",
] }
-derive_more = { workspace = true, features = ["deref", "deref_mut"]}
async-trait = { workspace = true }
base64 = { workspace = true }
bitflags = { workspace = true }
@@ -41,6 +40,7 @@ color-thief = { workspace = true }
const_format = { workspace = true }
dashmap = { workspace = true }
deadpool-redis.workspace = true
+derive_more = { workspace = true, features = ["deref", "deref_mut"] }
dotenvy = { workspace = true }
either = { workspace = true }
eyre = { workspace = true }
@@ -112,6 +112,7 @@ sqlx = { workspace = true, features = [
"rust_decimal",
"tls-rustls-aws-lc-rs",
] }
+sqlx-tracing = { workspace = true, features = ["postgres"] }
strum = { workspace = true }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "sync"] }
diff --git a/apps/labrinth/src/auth/checks.rs b/apps/labrinth/src/auth/checks.rs
index f56036df8..329e07104 100644
--- a/apps/labrinth/src/auth/checks.rs
+++ b/apps/labrinth/src/auth/checks.rs
@@ -1,4 +1,5 @@
use crate::database;
+use crate::database::PgPool;
use crate::database::models::project_item::ProjectQueryResult;
use crate::database::models::version_item::VersionQueryResult;
use crate::database::models::{DBCollection, DBOrganization, DBTeamMember};
@@ -8,7 +9,6 @@ use crate::models::users::User;
use crate::routes::ApiError;
use futures::TryStreamExt;
use itertools::Itertools;
-use sqlx::PgPool;
pub trait ValidateAuthorized {
fn validate_authorized(
diff --git a/apps/labrinth/src/auth/oauth/mod.rs b/apps/labrinth/src/auth/oauth/mod.rs
index 5a5d54670..d3fc5df6e 100644
--- a/apps/labrinth/src/auth/oauth/mod.rs
+++ b/apps/labrinth/src/auth/oauth/mod.rs
@@ -3,6 +3,7 @@ use std::fmt::Write;
use crate::auth::get_user_from_headers;
use crate::auth::oauth::uris::{OAuthRedirectUris, ValidatedRedirectUri};
use crate::auth::validate::extract_authorization_header;
+use crate::database::PgPool;
use crate::database::models::flow_item::DBFlow;
use crate::database::models::oauth_client_authorization_item::DBOAuthClientAuthorization;
use crate::database::models::oauth_client_item::DBOAuthClient;
@@ -24,7 +25,6 @@ use rand::distributions::Alphanumeric;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaCha20Rng;
use serde::{Deserialize, Serialize};
-use sqlx::postgres::PgPool;
use self::errors::{OAuthError, OAuthErrorType};
@@ -288,7 +288,7 @@ pub async fn request_token(
client_id,
user_id,
}
- .insert(&mut *transaction)
+ .insert(&mut transaction)
.await?;
transaction.commit().await?;
diff --git a/apps/labrinth/src/auth/validate.rs b/apps/labrinth/src/auth/validate.rs
index 97abe100f..fe3644ebd 100644
--- a/apps/labrinth/src/auth/validate.rs
+++ b/apps/labrinth/src/auth/validate.rs
@@ -18,7 +18,7 @@ pub async fn get_maybe_user_from_headers<'a, E>(
required_scopes: Scopes,
) -> Result