From 4d8e1a72418bdf990eca5831b097f9e4e28712f1 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Wed, 23 Nov 2022 13:32:27 -0600
Subject: [PATCH 01/87] Enable lazy loading for images

---
 templates/admin.rs.html | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/templates/admin.rs.html b/templates/admin.rs.html
index 1af6bc2..e457ce7 100644
--- a/templates/admin.rs.html
+++ b/templates/admin.rs.html
@@ -6,7 +6,7 @@
 <div class="admin">
   <div class="left">
     <figure class="avatar">
-      <img src="@contact.avatar" alt="@contact.display_name's avatar">
+      <img loading="lazy" src="@contact.avatar" alt="@contact.display_name's avatar">
     </figure>
   </div>
   <div class="right">

From b5dc3e7c08d507fb5a81fa4ced61b2b3f7a17297 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 6 Dec 2022 17:54:57 -0600
Subject: [PATCH 02/87] Wrap whole main in actix_rt, fixes opentelemetry

---
 src/main.rs | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index a428991..f31f63c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -2,6 +2,7 @@
 #![allow(clippy::needless_borrow)]
 
 use activitystreams::iri_string::types::IriString;
+use actix_rt::task::JoinHandle;
 use actix_web::{middleware::Compress, web, App, HttpServer};
 use collector::MemoryCollector;
 #[cfg(feature = "console")]
@@ -94,7 +95,8 @@ fn init_subscriber(
     Ok(())
 }
 
-fn main() -> Result<(), anyhow::Error> {
+#[actix_rt::main]
+async fn main() -> Result<(), anyhow::Error> {
     dotenv::dotenv().ok();
 
     let config = Config::build()?;
@@ -106,7 +108,7 @@ fn main() -> Result<(), anyhow::Error> {
     let args = Args::new();
 
     if args.any() {
-        return client_main(config, args);
+        return client_main(config, args).await?;
     }
 
     tracing::warn!("Opening DB");
@@ -116,16 +118,15 @@ fn main() -> Result<(), anyhow::Error> {
     let actors = ActorCache::new(db.clone());
     let media = MediaCache::new(db.clone());
 
-    server_main(db, actors, media, collector, config)?;
+    server_main(db, actors, media, collector, config).await??;
 
     tracing::warn!("Application exit");
 
     Ok(())
 }
 
-#[actix_rt::main]
-async fn client_main(config: Config, args: Args) -> Result<(), anyhow::Error> {
-    actix_rt::spawn(do_client_main(config, args)).await?
+fn client_main(config: Config, args: Args) -> JoinHandle<Result<(), anyhow::Error>> {
+    actix_rt::spawn(do_client_main(config, args))
 }
 
 async fn do_client_main(config: Config, args: Args) -> Result<(), anyhow::Error> {
@@ -174,15 +175,14 @@ async fn do_client_main(config: Config, args: Args) -> Result<(), anyhow::Error>
     Ok(())
 }
 
-#[actix_rt::main]
-async fn server_main(
+fn server_main(
     db: Db,
     actors: ActorCache,
     media: MediaCache,
     collector: MemoryCollector,
     config: Config,
-) -> Result<(), anyhow::Error> {
-    actix_rt::spawn(do_server_main(db, actors, media, collector, config)).await?
+) -> JoinHandle<Result<(), anyhow::Error>> {
+    actix_rt::spawn(do_server_main(db, actors, media, collector, config))
 }
 
 async fn do_server_main(

From b9dba28207036ed2e5a7fd18ce8d7b4cab9e217d Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 6 Dec 2022 18:21:55 -0600
Subject: [PATCH 03/87] Bump activitystreams

---
 Cargo.lock       | 226 ++++++++++++++++++++++++++++++-----------------
 Cargo.toml       |   4 +-
 src/jobs/apub.rs |   4 +-
 3 files changed, 151 insertions(+), 83 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5bd9064..0224515 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "activitystreams"
-version = "0.7.0-alpha.20"
+version = "0.7.0-alpha.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "459a89e7d449cf49e57044d59dcf637d2927362b7a75737c90bd3679ba476a78"
+checksum = "a3b81ea88d9e6c12a023479a2638f2f50853ec7e6fbaba1e9f94d6224814e634"
 dependencies = [
  "activitystreams-kinds",
  "iri-string",
@@ -18,9 +18,9 @@ dependencies = [
 
 [[package]]
 name = "activitystreams-ext"
-version = "0.1.0-alpha.2"
+version = "0.1.0-alpha.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb8e19a0810cc25df3535061a08b7d8f8a734d309ea4411c57a9767e4a2ffa0e"
+checksum = "cd4cc5f95aabf2bc2e0672400f7494094ffae30b597317cb825b4ac5c8a405b3"
 dependencies = [
  "activitystreams",
  "serde",
@@ -279,9 +279,9 @@ dependencies = [
 
 [[package]]
 name = "ammonia"
-version = "3.2.1"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4b477377562f3086b7778d241786e9406b883ccfaa03557c0fe0924b9349f13a"
+checksum = "64e6d1c7838db705c9b756557ee27c384ce695a1c51a6fe528784cb1c6840170"
 dependencies = [
  "html5ever",
  "maplit",
@@ -410,26 +410,15 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.58"
+version = "0.1.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e805d94e6b5001b651426cf4cd446b1ab5f319d27bab5c644f61de0a804360c"
+checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
 dependencies = [
  "proc-macro2",
  "quote",
  "syn",
 ]
 
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi",
- "libc",
- "winapi",
-]
-
 [[package]]
 name = "autocfg"
 version = "1.1.0"
@@ -472,9 +461,9 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.5.17"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acee9fd5073ab6b045a275b3e709c163dd36c90685219cb21804a147b58dba43"
+checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -490,9 +479,9 @@ dependencies = [
  "mime",
  "percent-encoding",
  "pin-project-lite",
+ "rustversion",
  "serde",
  "sync_wrapper",
- "tokio",
  "tower",
  "tower-http",
  "tower-layer",
@@ -501,9 +490,9 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.2.9"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37e5939e02c56fecd5c017c37df4238c0a839fa76b7f97acdd7efb804fd181cc"
+checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92"
 dependencies = [
  "async-trait",
  "bytes",
@@ -511,6 +500,7 @@ dependencies = [
  "http",
  "http-body",
  "mime",
+ "rustversion",
  "tower-layer",
  "tower-service",
 ]
@@ -715,14 +705,14 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.0.26"
+version = "4.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2148adefda54e14492fb9bddcc600b4344c5d1a3123bd666dcb939c6f0e0e57e"
+checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
 dependencies = [
- "atty",
  "bitflags",
  "clap_derive",
  "clap_lex",
+ "is-terminal",
  "once_cell",
  "strsim",
  "termcolor",
@@ -752,9 +742,9 @@ dependencies = [
 
 [[package]]
 name = "config"
-version = "0.13.2"
+version = "0.13.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11f1667b8320afa80d69d8bbe40830df2c8a06003d86f73d8e003b2c48df416d"
+checksum = "d379af7f68bfc21714c6c7dea883544201741d2ce8274bb12fa54f89507f52a7"
 dependencies = [
  "async-trait",
  "json5",
@@ -933,14 +923,14 @@ dependencies = [
  "hashbrown",
  "lock_api",
  "once_cell",
- "parking_lot_core 0.9.4",
+ "parking_lot_core 0.9.5",
 ]
 
 [[package]]
 name = "der"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13dd2ae565c0a381dde7fade45fce95984c568bdcb4700a4fdbe3175e0380b2f"
+checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
 dependencies = [
  "const-oid",
  "pem-rfc7468",
@@ -1023,6 +1013,27 @@ dependencies = [
  "scopeguard",
 ]
 
+[[package]]
+name = "errno"
+version = "0.2.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+dependencies = [
+ "errno-dragonfly",
+ "libc",
+ "winapi",
+]
+
+[[package]]
+name = "errno-dragonfly"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf"
+dependencies = [
+ "cc",
+ "libc",
+]
+
 [[package]]
 name = "event-listener"
 version = "2.5.3"
@@ -1046,9 +1057,9 @@ checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
 
 [[package]]
 name = "flate2"
-version = "1.0.24"
+version = "1.0.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f82b0f4c27ad9f8bfd1f3208d882da2b09c301bc1c828fd3a00d0216d2fbbff6"
+checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -1270,6 +1281,15 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hermit-abi"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7"
+dependencies = [
+ "libc",
+]
+
 [[package]]
 name = "html5ever"
 version = "0.26.0"
@@ -1314,9 +1334,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
 
 [[package]]
 name = "http-signature-normalization"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f8f45adbef81d7ea3bd7e9bcc6734b7245dad05a14abdcc7ddc0988791d63515"
+checksum = "8b93438e69bb70b5c01d144da52b9e17505d84b9b84a6dc70d2750365df9ca6e"
 dependencies = [
  "httpdate",
 ]
@@ -1453,6 +1473,16 @@ dependencies = [
  "cfg-if",
 ]
 
+[[package]]
+name = "io-lifetimes"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
 [[package]]
 name = "ipnet"
 version = "2.5.1"
@@ -1468,6 +1498,18 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "is-terminal"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
+dependencies = [
+ "hermit-abi 0.2.6",
+ "io-lifetimes",
+ "rustix",
+ "windows-sys",
+]
+
 [[package]]
 name = "itertools"
 version = "0.9.0"
@@ -1542,9 +1584,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.137"
+version = "0.2.138"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc7fcc620a3bff7cdd7a365be3376c97191aeaccc2a603e600951e452615bf89"
+checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
 
 [[package]]
 name = "libm"
@@ -1558,6 +1600,12 @@ version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
+[[package]]
+name = "linux-raw-sys"
+version = "0.1.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
+
 [[package]]
 name = "local-channel"
 version = "0.1.3"
@@ -1650,9 +1698,9 @@ dependencies = [
 
 [[package]]
 name = "matchit"
-version = "0.5.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "73cbba799671b762df5a175adf59ce145165747bb891505c43d09aefbbf38beb"
+checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40"
 
 [[package]]
 name = "md5"
@@ -1765,9 +1813,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.5.4"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96590ba8f175222643a85693f33d26e9c8a015f599c216509b1a6894af675d34"
+checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
 dependencies = [
  "adler",
 ]
@@ -1932,7 +1980,7 @@ version = "1.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.1.19",
  "libc",
 ]
 
@@ -2071,7 +2119,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.4",
+ "parking_lot_core 0.9.5",
 ]
 
 [[package]]
@@ -2090,9 +2138,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.4"
+version = "0.9.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dc9e0dc2adc1c69d09143aff38d3d30c5c3f0df0dad82e6d25547af174ebec0"
+checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
 dependencies = [
  "cfg-if",
  "libc",
@@ -2141,9 +2189,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.4.1"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a528564cc62c19a7acac4d81e01f39e53e25e17b934878f4c6d25cc2836e62f8"
+checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2151,9 +2199,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.4.1"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d5fd9bc6500181952d34bd0b2b0163a54d794227b498be0b7afa7698d0a7b18f"
+checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2161,9 +2209,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.4.1"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d2610d5ac5156217b4ff8e46ddcef7cdf44b273da2ac5bca2ecbfa86a330e7c4"
+checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2174,9 +2222,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.4.1"
+version = "2.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "824749bf7e21dd66b36fbe26b3f45c713879cccd4a009a917ab8e045ca8246fe"
+checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20"
 dependencies = [
  "once_cell",
  "pest",
@@ -2348,9 +2396,9 @@ dependencies = [
 
 [[package]]
 name = "prost"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0841812012b2d4a6145fae9a6af1534873c32aa67fff26bd09f8fa42c83f95a"
+checksum = "c0b18e655c21ff5ac2084a5ad0611e827b3f92badf79f4910b5a5c58f4d87ff0"
 dependencies = [
  "bytes",
  "prost-derive",
@@ -2358,9 +2406,9 @@ dependencies = [
 
 [[package]]
 name = "prost-build"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1d8b442418ea0822409d9e7d047cbf1e7e9e1760b172bf9982cf29d517c93511"
+checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604"
 dependencies = [
  "bytes",
  "heck",
@@ -2686,6 +2734,20 @@ dependencies = [
  "semver",
 ]
 
+[[package]]
+name = "rustix"
+version = "0.36.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
+dependencies = [
+ "bitflags",
+ "errno",
+ "io-lifetimes",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
 [[package]]
 name = "rustls"
 version = "0.20.7"
@@ -2707,6 +2769,12 @@ dependencies = [
  "base64",
 ]
 
+[[package]]
+name = "rustversion"
+version = "1.0.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
+
 [[package]]
 name = "ryu"
 version = "1.0.11"
@@ -2737,18 +2805,18 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
 
 [[package]]
 name = "serde"
-version = "1.0.147"
+version = "1.0.149"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d193d69bae983fc11a79df82342761dfbf28a99fc8d203dca4c3c1b590948965"
+checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.147"
+version = "1.0.149"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f1d362ca8fc9c3e3a7484440752472d68a6caa98f1ab81d99b5dfe517cec852"
+checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2955,9 +3023,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
-version = "1.0.103"
+version = "1.0.105"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a864042229133ada95abf3b54fdc62ef5ccabe9515b64717bcb9a1919e59445d"
+checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2990,9 +3058,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
 
 [[package]]
 name = "teloxide"
-version = "0.11.2"
+version = "0.11.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19017dde82bddcbbdf8e40484f23985f4097b1baef4f7c0e006195ad1e6d4e3c"
+checksum = "59c3b28292b33a57a8d71ce000c23fdaffeb0b4aec35fa9351d4be7ec6376a3f"
 dependencies = [
  "aquamarine",
  "bytes",
@@ -3164,9 +3232,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
 name = "tokio"
-version = "1.22.0"
+version = "1.23.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76ce4a75fb488c605c54bf610f221cea8b0dafb53333c1a67e8ee199dcd2ae3"
+checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3179,7 +3247,7 @@ dependencies = [
  "socket2",
  "tokio-macros",
  "tracing",
- "winapi",
+ "windows-sys",
 ]
 
 [[package]]
@@ -3194,9 +3262,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-macros"
-version = "1.8.0"
+version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
+checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3250,9 +3318,9 @@ dependencies = [
 
 [[package]]
 name = "tonic"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55b9af819e54b8f33d453655bef9b9acc171568fb49523078d0cc4e7484200ec"
+checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb"
 dependencies = [
  "async-stream",
  "async-trait",
@@ -3282,9 +3350,9 @@ dependencies = [
 
 [[package]]
 name = "tonic-build"
-version = "0.8.2"
+version = "0.8.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c6fd7c2581e36d63388a9e04c350c21beb7a8b059580b2e93993c526899ddc"
+checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4"
 dependencies = [
  "prettyplease",
  "proc-macro2",
@@ -3315,9 +3383,9 @@ dependencies = [
 
 [[package]]
 name = "tower-http"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c530c8675c1dbf98facee631536fa116b5fb6382d7dd6dc1b118d970eafe3ba"
+checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858"
 dependencies = [
  "bitflags",
  "bytes",
@@ -3476,9 +3544,9 @@ checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
 
 [[package]]
 name = "typenum"
-version = "1.15.0"
+version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba"
 
 [[package]]
 name = "ucd-trie"
diff --git a/Cargo.toml b/Cargo.toml
index fbc9e5f..3725628 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,8 +29,8 @@ actix-web = { version = "4.0.1", default-features = false, features = [
   "compress-gzip",
 ] }
 actix-webfinger = "0.4.0"
-activitystreams = "0.7.0-alpha.19"
-activitystreams-ext = "0.1.0-alpha.2"
+activitystreams = "0.7.0-alpha.21"
+activitystreams-ext = "0.1.0-alpha.3"
 ammonia = "3.1.0"
 awc = { version = "3.0.0", default-features = false, features = ["rustls"] }
 bcrypt = "0.13"
diff --git a/src/jobs/apub.rs b/src/jobs/apub.rs
index d857b46..a5e195c 100644
--- a/src/jobs/apub.rs
+++ b/src/jobs/apub.rs
@@ -36,13 +36,13 @@ async fn get_inboxes(
     state.inboxes_without(&actor.inbox, &authority).await
 }
 
-fn prepare_activity<T, U, V, Kind>(
+fn prepare_activity<T, U, V>(
     mut t: T,
     id: impl TryInto<IriString, Error = U>,
     to: impl TryInto<IriString, Error = V>,
 ) -> Result<T, Error>
 where
-    T: ObjectExt<Kind> + BaseExt<Kind>,
+    T: ObjectExt + BaseExt,
     Error: From<U> + From<V>,
 {
     t.set_id(id.try_into()?)

From a0fbf9d2367c6fff9f3d91ccece94be264436467 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 6 Dec 2022 18:53:19 -0600
Subject: [PATCH 04/87] Bump activitystreams again

---
 Cargo.lock    | 13 ++++++------
 src/config.rs | 57 +++++++++++++++++++++++++++++++++------------------
 src/error.rs  |  5 +----
 3 files changed, 45 insertions(+), 30 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0224515..457d221 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "activitystreams"
-version = "0.7.0-alpha.21"
+version = "0.7.0-alpha.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3b81ea88d9e6c12a023479a2638f2f50853ec7e6fbaba1e9f94d6224814e634"
+checksum = "713061473d42baa5527b1dbf07b86a506c48df3190a4fb840fb7fcea8cf1b724"
 dependencies = [
  "activitystreams-kinds",
  "iri-string",
@@ -29,9 +29,9 @@ dependencies = [
 
 [[package]]
 name = "activitystreams-kinds"
-version = "0.2.1"
+version = "0.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d014a4fb8828870b7b46bee6257b9a89d06188ae8d435381ba94f14c8c697d8"
+checksum = "e97dfe76efd8c0b113cc3580a6b5f4acba47662e3cfbbfcce081c9ac89798990"
 dependencies = [
  "iri-string",
  "serde",
@@ -1491,10 +1491,11 @@ checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
 
 [[package]]
 name = "iri-string"
-version = "0.5.6"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf071934ee7ee97e52fa1868a9540a7885eab75926bd70794030304a9797cea1"
+checksum = "21859b667d66a4c1dacd9df0863b3efb65785474255face87f5bca39dd8407c0"
 dependencies = [
+ "memchr",
  "serde",
 ]
 
diff --git a/src/config.rs b/src/config.rs
index 1d4cf86..61aa7a9 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -8,6 +8,7 @@ use crate::{
 use activitystreams::{
     iri,
     iri_string::{
+        format::ToDedicatedString,
         resolve::FixedBaseResolver,
         types::{IriAbsoluteString, IriFragmentStr, IriRelativeStr, IriString},
     },
@@ -398,34 +399,42 @@ impl Config {
     #[tracing::instrument(level = "debug", skip_all, fields(base_uri = tracing::field::debug(&self.base_uri), kind = tracing::field::debug(&kind)))]
     fn do_generate_url(&self, kind: UrlKind) -> Result<IriString, Error> {
         let iri = match kind {
-            UrlKind::Activity => FixedBaseResolver::new(self.base_uri.as_ref()).try_resolve(
-                IriRelativeStr::new(&format!("activity/{}", Uuid::new_v4()))?.as_ref(),
-            )?,
+            UrlKind::Activity => FixedBaseResolver::new(self.base_uri.as_ref())
+                .resolve(IriRelativeStr::new(&format!("activity/{}", Uuid::new_v4()))?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::Actor => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("actor")?.as_ref())?,
+                .resolve(IriRelativeStr::new("actor")?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::Followers => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("followers")?.as_ref())?,
+                .resolve(IriRelativeStr::new("followers")?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::Following => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("following")?.as_ref())?,
+                .resolve(IriRelativeStr::new("following")?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::Inbox => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("inbox")?.as_ref())?,
+                .resolve(IriRelativeStr::new("inbox")?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::Index => self.base_uri.clone().into(),
             UrlKind::MainKey => {
                 let actor = IriRelativeStr::new("actor")?;
                 let fragment = IriFragmentStr::new("main-key")?;
 
-                let mut resolved =
-                    FixedBaseResolver::new(self.base_uri.as_ref()).try_resolve(actor.as_ref())?;
+                let mut resolved = FixedBaseResolver::new(self.base_uri.as_ref())
+                    .resolve(actor.as_ref())
+                    .try_to_dedicated_string()?;
 
                 resolved.set_fragment(Some(fragment));
                 resolved
             }
             UrlKind::Media(uuid) => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new(&format!("media/{}", uuid))?.as_ref())?,
+                .resolve(IriRelativeStr::new(&format!("media/{}", uuid))?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::NodeInfo => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("nodeinfo/2.0.json")?.as_ref())?,
+                .resolve(IriRelativeStr::new("nodeinfo/2.0.json")?.as_ref())
+                .try_to_dedicated_string()?,
             UrlKind::Outbox => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("outbox")?.as_ref())?,
+                .resolve(IriRelativeStr::new("outbox")?.as_ref())
+                .try_to_dedicated_string()?,
         };
 
         Ok(iri)
@@ -439,21 +448,29 @@ impl Config {
     fn do_generate_admin_url(&self, kind: AdminUrlKind) -> Result<IriString, Error> {
         let iri = match kind {
             AdminUrlKind::Allow => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/allow")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/allow")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Disallow => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/disallow")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/disallow")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Block => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/block")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/block")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Unblock => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/unblock")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/unblock")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Allowed => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/allowed")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/allowed")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Blocked => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/blocked")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/blocked")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Connected => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/connected")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/connected")?.as_ref())
+                .try_to_dedicated_string()?,
             AdminUrlKind::Stats => FixedBaseResolver::new(self.base_uri.as_ref())
-                .try_resolve(IriRelativeStr::new("api/v1/admin/stats")?.as_ref())?,
+                .resolve(IriRelativeStr::new("api/v1/admin/stats")?.as_ref())
+                .try_to_dedicated_string()?,
         };
 
         Ok(iri)
diff --git a/src/error.rs b/src/error.rs
index 8fcd05d..f399ebe 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -77,10 +77,7 @@ pub(crate) enum ErrorKind {
     ParseIri(#[from] activitystreams::iri_string::validate::Error),
 
     #[error("Couldn't normalize IRI, {0}")]
-    NormalizeIri(
-        #[from]
-        activitystreams::iri_string::task::Error<activitystreams::iri_string::normalize::Error>,
-    ),
+    NormalizeIri(#[from] std::collections::TryReserveError),
 
     #[error("Couldn't perform IO, {0}")]
     Io(#[from] io::Error),

From c543e8b4eba6e2c1b145657b9ad3752898543f02 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 6 Dec 2022 18:53:36 -0600
Subject: [PATCH 05/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 457d221..30c96ce 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.66"
+version = "0.3.67"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 3725628..99ab955 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.66"
+version = "0.3.67"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 8575439d88e726459674f79897adc78cc85c7226 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 8 Dec 2022 15:14:04 -0600
Subject: [PATCH 06/87] Bump deps

---
 Cargo.lock | 16 ++++++++--------
 Cargo.toml |  2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 30c96ce..ceac48b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1334,18 +1334,18 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
 
 [[package]]
 name = "http-signature-normalization"
-version = "0.6.1"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b93438e69bb70b5c01d144da52b9e17505d84b9b84a6dc70d2750365df9ca6e"
+checksum = "b95e3149194de5f3f9d5225bcc6a8677979f8ff8ce39c85654730ad4824f101e"
 dependencies = [
  "httpdate",
 ]
 
 [[package]]
 name = "http-signature-normalization-actix"
-version = "0.6.2"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7483d0ee4d093fa4bfe5956cd405492c07808a5064a29cfe3960d474f21f39c2"
+checksum = "d1042c9eb8c9882f94be2da71787168de008f962c400706f692901238726b64d"
 dependencies = [
  "actix-http",
  "actix-rt",
@@ -1406,9 +1406,9 @@ dependencies = [
 
 [[package]]
 name = "hyper-rustls"
-version = "0.23.1"
+version = "0.23.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59df7c4e19c950e6e0e868dcc0a300b09a9b88e9ec55bd879ca819087a77355d"
+checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
 dependencies = [
  "http",
  "hyper",
@@ -1485,9 +1485,9 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.5.1"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f88c5561171189e69df9d98bcf18fd5f9558300f7ea7b801eb8a0fd748bd8745"
+checksum = "ec947b7a4ce12e3b87e353abae7ce124d025b6c7d6c5aea5cc0bcf92e9510ded"
 
 [[package]]
 name = "iri-string"
diff --git a/Cargo.toml b/Cargo.toml
index 99ab955..70289c1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -86,7 +86,7 @@ default-features = false
 features = ["background-jobs-actix", "error-logging"]
 
 [dependencies.http-signature-normalization-actix]
-version = "0.6.0"
+version = "0.7.0"
 default-features = false
 features = ["client", "server", "sha-2"]
 

From c18760d57f85030807a171ba1bca2731d336a9eb Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 8 Dec 2022 15:14:12 -0600
Subject: [PATCH 07/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ceac48b..9ffb653 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.67"
+version = "0.3.68"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 70289c1..7d5768b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.67"
+version = "0.3.68"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From d834537300a52104dab393962d53aaaf8b19a973 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 8 Dec 2022 21:15:43 -0600
Subject: [PATCH 08/87] Bump http-signature-normalization-actix

---
 Cargo.lock | 6 +++---
 Cargo.toml | 4 ++--
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 9ffb653..ba33727 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.68"
+version = "0.3.69"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
@@ -1343,9 +1343,9 @@ dependencies = [
 
 [[package]]
 name = "http-signature-normalization-actix"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1042c9eb8c9882f94be2da71787168de008f962c400706f692901238726b64d"
+checksum = "60d41016e2fd353e0a3f266ca9ac9b9dbf439c4a2bede3b400ba7ea73ac9bb3f"
 dependencies = [
  "actix-http",
  "actix-rt",
diff --git a/Cargo.toml b/Cargo.toml
index 7d5768b..8a4d9c6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.68"
+version = "0.3.69"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"
@@ -86,7 +86,7 @@ default-features = false
 features = ["background-jobs-actix", "error-logging"]
 
 [dependencies.http-signature-normalization-actix]
-version = "0.7.0"
+version = "0.7.1"
 default-features = false
 features = ["client", "server", "sha-2"]
 

From f4db90b699465a7513906a62a4d4ab30c0d1313b Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 9 Dec 2022 17:47:45 -0600
Subject: [PATCH 09/87] Use sync RwLock for lru access

---
 src/data/state.rs         | 11 +++++------
 src/jobs/apub/announce.rs |  2 +-
 src/routes/inbox.rs       |  2 +-
 3 files changed, 7 insertions(+), 8 deletions(-)

diff --git a/src/data/state.rs b/src/data/state.rs
index 93a3f9a..31f0811 100644
--- a/src/data/state.rs
+++ b/src/data/state.rs
@@ -10,8 +10,7 @@ use actix_web::web;
 use lru::LruCache;
 use rand::thread_rng;
 use rsa::{RsaPrivateKey, RsaPublicKey};
-use std::sync::Arc;
-use tokio::sync::RwLock;
+use std::sync::{Arc, RwLock};
 
 #[derive(Clone)]
 pub struct State {
@@ -78,12 +77,12 @@ impl State {
             .collect())
     }
 
-    pub(crate) async fn is_cached(&self, object_id: &IriString) -> bool {
-        self.object_cache.read().await.contains(object_id)
+    pub(crate) fn is_cached(&self, object_id: &IriString) -> bool {
+        self.object_cache.read().unwrap().contains(object_id)
     }
 
-    pub(crate) async fn cache(&self, object_id: IriString, actor_id: IriString) {
-        self.object_cache.write().await.put(object_id, actor_id);
+    pub(crate) fn cache(&self, object_id: IriString, actor_id: IriString) {
+        self.object_cache.write().unwrap().put(object_id, actor_id);
     }
 
     #[tracing::instrument(level = "debug", name = "Building state", skip_all)]
diff --git a/src/jobs/apub/announce.rs b/src/jobs/apub/announce.rs
index 93dec67..480f8db 100644
--- a/src/jobs/apub/announce.rs
+++ b/src/jobs/apub/announce.rs
@@ -42,7 +42,7 @@ impl Announce {
             .queue(DeliverMany::new(inboxes, announce)?)
             .await?;
 
-        state.state.cache(self.object_id, activity_id).await;
+        state.state.cache(self.object_id, activity_id);
         Ok(())
     }
 }
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 14286df..472b97d 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -203,7 +203,7 @@ async fn handle_announce(
         .as_single_id()
         .ok_or(ErrorKind::MissingId)?;
 
-    if state.is_cached(object_id).await {
+    if state.is_cached(object_id) {
         return Err(ErrorKind::Duplicate.into());
     }
 

From 31021e80e4b93a013108cc410b18c190bd735341 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 9 Dec 2022 18:03:36 -0600
Subject: [PATCH 10/87] Bump deps

---
 Cargo.lock | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ba33727..06e0f6e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -538,9 +538,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-core"
-version = "0.14.1"
+version = "0.14.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1274e49ae8eff1fc6b4943660e59ce2f2e13e65a23a707924a50a40c7b94fc4d"
+checksum = "5853856c74137313e8a7b1394e737cf03b03db0c2cb7c0a59d0b5507a65135ba"
 dependencies = [
  "actix-rt",
  "anyhow",
@@ -2336,9 +2336,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "15eb2c6e362923af47e13c23ca5afb859e83d54452c55b0b9ac763b8f7c1ac16"
+checksum = "ac662b3a6490de378b0ee15cf2dfff7127aebfe0b19acc65e7fbca3d299c3788"
 
 [[package]]
 name = "ppv-lite86"
@@ -2407,9 +2407,9 @@ dependencies = [
 
 [[package]]
 name = "prost-build"
-version = "0.11.3"
+version = "0.11.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e330bf1316db56b12c2bcfa399e8edddd4821965ea25ddb2c134b610b1c1c604"
+checksum = "276470f7f281b0ed53d2ae42dd52b4a8d08853a3c70e7fe95882acbb98a6ae94"
 dependencies = [
  "bytes",
  "heck",

From 6082def85423aa39f34efc9b6f817ecfb0e712d8 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 9 Dec 2022 18:04:15 -0600
Subject: [PATCH 11/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 06e0f6e..7c66816 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.69"
+version = "0.3.70"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 8a4d9c6..0efc9e0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.69"
+version = "0.3.70"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From a8b8325557630ecd9c48ac6c4042b959e30acf4c Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 12 Dec 2022 10:56:53 -0600
Subject: [PATCH 12/87] Update deps

---
 Cargo.lock | 24 ++++++++++++------------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7c66816..08fe464 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -517,9 +517,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-actix"
-version = "0.14.2"
+version = "0.14.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99f8bfe0a984c8d0bc7e67b376cc05e0b9015fdd3ee878900046120ef781c47e"
+checksum = "a5a08fca1cf46ead9e7643596ded92049af683fec54b073fe1f36a0c7874f9be"
 dependencies = [
  "actix-rt",
  "anyhow",
@@ -538,9 +538,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-core"
-version = "0.14.2"
+version = "0.14.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5853856c74137313e8a7b1394e737cf03b03db0c2cb7c0a59d0b5507a65135ba"
+checksum = "3b102461c17491eb9ebf4fb974fa894cdc7516deada3cbdc0761a32e35f64322"
 dependencies = [
  "actix-rt",
  "anyhow",
@@ -1485,9 +1485,9 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec947b7a4ce12e3b87e353abae7ce124d025b6c7d6c5aea5cc0bcf92e9510ded"
+checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
 
 [[package]]
 name = "iri-string"
@@ -2806,18 +2806,18 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
 
 [[package]]
 name = "serde"
-version = "1.0.149"
+version = "1.0.150"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "256b9932320c590e707b94576e3cc1f7c9024d0ee6612dfbcf1cb106cbe8e055"
+checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.149"
+version = "1.0.150"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4eae9b04cbffdfd550eb462ed33bc6a1b68c935127d008b27444d08380f94e4"
+checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3741,9 +3741,9 @@ dependencies = [
 
 [[package]]
 name = "webpki-roots"
-version = "0.22.5"
+version = "0.22.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "368bfe657969fb01238bb756d351dcade285e0f6fcbd36dcb23359a5169975be"
+checksum = "b6c71e40d7d2c34a5106301fb632274ca37242cd0c9d3e64dbece371a40a2d87"
 dependencies = [
  "webpki",
 ]

From 9d68ccd834529dcd1f42ca3dd67727d263d8384e Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 12 Dec 2022 11:06:23 -0600
Subject: [PATCH 13/87] Update deps

---
 Cargo.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 08fe464..b658c15 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -517,9 +517,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-actix"
-version = "0.14.3"
+version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5a08fca1cf46ead9e7643596ded92049af683fec54b073fe1f36a0c7874f9be"
+checksum = "e7a36626c73630619c8d044a4ee52336e283bc0cfa0f60b17c9ee0bd55dec455"
 dependencies = [
  "actix-rt",
  "anyhow",

From a0dc2363f6de94fd835a2bd24a4e0aeee996c87c Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 10:35:16 -0600
Subject: [PATCH 14/87] Add support for Add activity - forward verbatim

---
 src/apub.rs         | 1 +
 src/routes/inbox.rs | 4 +++-
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/apub.rs b/src/apub.rs
index 2b922e3..48f64d4 100644
--- a/src/apub.rs
+++ b/src/apub.rs
@@ -33,6 +33,7 @@ pub struct PublicKey {
 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "PascalCase")]
 pub enum ValidTypes {
+    Add,
     Accept,
     Announce,
     Create,
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 472b97d..38d492a 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -71,7 +71,9 @@ pub(crate) async fn route(
             handle_announce(&state, &jobs, input, actor).await?
         }
         ValidTypes::Follow => handle_follow(&config, &jobs, input, actor).await?,
-        ValidTypes::Delete | ValidTypes::Update => handle_forward(&jobs, input, actor).await?,
+        ValidTypes::Add | ValidTypes::Delete | ValidTypes::Update => {
+            handle_forward(&jobs, input, actor).await?
+        }
         ValidTypes::Undo => handle_undo(&config, &jobs, input, actor, is_connected).await?,
     };
 

From 43b70f88a7c87d9159f74234e7b901ca59857973 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 10:39:25 -0600
Subject: [PATCH 15/87] Apply patch from perallamint on github

 clippy: unnecessary lifetime annotation on static strings

Since string literal constant already has static lifetime, it is not
necessary to explicitly annotate it with 'static.
---
 src/jobs/instance.rs       | 4 ++--
 src/middleware/verifier.rs | 8 ++++----
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/src/jobs/instance.rs b/src/jobs/instance.rs
index 4339845..2f1e5c7 100644
--- a/src/jobs/instance.rs
+++ b/src/jobs/instance.rs
@@ -148,8 +148,8 @@ struct Contact {
 mod tests {
     use super::Instance;
 
-    const ASONIX_INSTANCE: &'static str = r#"{"uri":"masto.asonix.dog","title":"asonix.dog","short_description":"The asonix of furry mastodon. For me and a few friends. DM me somewhere if u want an account lol","description":"A mastodon server that's only for me and nobody else sorry","email":"asonix@asonix.dog","version":"4.0.0rc2-asonix-changes","urls":{"streaming_api":"wss://masto.asonix.dog"},"stats":{"user_count":7,"status_count":12328,"domain_count":5146},"thumbnail":"https://masto.asonix.dog/system/site_uploads/files/000/000/002/@1x/32f51462a2b2bf2d.png","languages":["dog"],"registrations":false,"approval_required":false,"invites_enabled":false,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":{"id":"1","username":"asonix","acct":"asonix","display_name":"Liom on Mane :antiverified:","locked":true,"bot":false,"discoverable":true,"group":false,"created_at":"2021-02-09T00:00:00.000Z","note":"\u003cp\u003e26, local liom, friend, rust (lang) stan, bi \u003c/p\u003e\u003cp\u003eicon by \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://furaffinity.net/user/lalupine\" target=\"blank\" rel=\"noopener noreferrer\" class=\"u-url mention\"\u003e@\u003cspan\u003elalupine@furaffinity.net\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003cbr /\u003eheader by \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://furaffinity.net/user/tronixx\" target=\"blank\" rel=\"noopener noreferrer\" class=\"u-url mention\"\u003e@\u003cspan\u003etronixx@furaffinity.net\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003eTestimonials:\u003c/p\u003e\u003cp\u003eStand: LIONS\u003cbr /\u003eStand User: AODE\u003cbr /\u003e- Keris (not on here)\u003c/p\u003e","url":"https://masto.asonix.dog/@asonix","avatar":"https://masto.asonix.dog/system/accounts/avatars/000/000/001/original/00852df0e6fee7e0.png","avatar_static":"https://masto.asonix.dog/system/accounts/avatars/000/000/001/original/00852df0e6fee7e0.png","header":"https://masto.asonix.dog/system/accounts/headers/000/000/001/original/8122ce3e5a745385.png","header_static":"https://masto.asonix.dog/system/accounts/headers/000/000/001/original/8122ce3e5a745385.png","followers_count":237,"following_count":474,"statuses_count":8798,"last_status_at":"2022-11-08","noindex":true,"emojis":[{"shortcode":"antiverified","url":"https://masto.asonix.dog/system/custom_emojis/images/000/030/053/original/bb0bc2e395b9a127.png","static_url":"https://masto.asonix.dog/system/custom_emojis/images/000/030/053/static/bb0bc2e395b9a127.png","visible_in_picker":true}],"fields":[{"name":"pronouns","value":"he/they","verified_at":null},{"name":"software","value":"bad","verified_at":null},{"name":"gitea","value":"\u003ca href=\"https://git.asonix.dog\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003egit.asonix.dog\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":null},{"name":"join my","value":"relay","verified_at":null}]},"rules":[]}"#;
-    const HYNET_INSTANCE: &'static str = r#"{"approval_required":false,"avatar_upload_limit":2000000,"background_image":"https://soc.hyena.network/images/city.jpg","background_upload_limit":4000000,"banner_upload_limit":4000000,"description":"Akkoma: The cooler fediverse server","description_limit":5000,"email":"me@hyena.network","languages":["en"],"max_toot_chars":"5000","pleroma":{"metadata":{"account_activation_required":true,"features":["pleroma_api","mastodon_api","mastodon_api_streaming","polls","v2_suggestions","pleroma_explicit_addressing","shareable_emoji_packs","multifetch","pleroma:api/v1/notifications:include_types_filter","chat","shout","relay","safe_dm_mentions","pleroma_emoji_reactions","pleroma_chat_messages","exposable_reactions","profile_directory","custom_emoji_reactions"],"federation":{"enabled":true,"exclusions":false,"mrf_hashtag":{"federated_timeline_removal":[],"reject":[],"sensitive":["nsfw"]},"mrf_policies":["SimplePolicy","EnsureRePrepended","HashtagPolicy"],"mrf_simple":{"accept":[],"avatar_removal":[],"banner_removal":[],"federated_timeline_removal":["botsin.space"],"followers_only":[],"media_nsfw":["mstdn.jp","wxw.moe","knzk.me","vipgirlfriend.xxx","humblr.social","switter.at","kinkyelephant.com","sinblr.com","kinky.business","rubber.social"],"media_removal":[],"reject":["*.10minutepleroma.com","101010.pl","13bells.com","2.distsn.org","2hu.club","2ndamendment.social","434.earth","4chan.icu","4qq.org","7td.org","80percent.social","a.nti.social","aaathats3as.com","accela.online","amala.schwartzwelt.xyz","angrytoday.com","anime.website","antitwitter.moe","antivaxxer.icu","archivefedifor.fun","artalley.social","bae.st","bajax.us","baraag.net","bbs.kawa-kun.com","beefyboys.club","beefyboys.win","bikeshed.party","bitcoinhackers.org","bleepp.com","blovice.bahnhof.cz","brighteon.social","buildthatwallandmakeamericagreatagain.trumpislovetrumpis.life","bungle.online","cawfee.club","censorship.icu","chungus.cc","club.darknight-coffee.org","clubcyberia.co","cock.fish","cock.li","comfyboy.club","contrapointsfan.club","coon.town","counter.social","cum.salon","d-fens.systems","definitely-not-archivefedifor.fun","degenerates.fail","desuposter.club","detroitriotcity.com","developer.gab.com","dogwhipping.day","eientei.org","enigmatic.observer","eveningzoo.club","exited.eu","federation.krowverse.services","fedi.cc","fedi.krowverse.services","fedi.pawlicker.com","fedi.vern.cc","freak.university","freeatlantis.com","freecumextremist.com","freesoftwareextremist.com","freespeech.firedragonstudios.com","freespeech.host","freespeechextremist.com","freevoice.space","freezepeach.xyz","froth.zone","fuckgov.org","gab.ai","gab.polaris-1.work","gab.protohype.net","gabfed.com","gameliberty.club","gearlandia.haus","gitmo.life","glindr.org","glittersluts.xyz","glowers.club","godspeed.moe","gorf.pub","goyim.app","gs.kawa-kun.com","hagra.net","hallsofamenti.io","hayu.sh","hentai.baby","honkwerx.tech","hunk.city","husk.site","iddqd.social","ika.moe","isexychat.space","jaeger.website","justicewarrior.social","kag.social","katiehopkinspolitical.icu","kiwifarms.cc","kiwifarms.is","kiwifarms.net","kohrville.net","koyu.space","kys.moe","lain.com","lain.sh","leafposter.club","lets.saynoto.lgbt","liberdon.com","libertarianism.club","ligma.pro","lolis.world","masochi.st","masthead.social","mastodon.digitalsuccess.dev","mastodon.fidonet.io","mastodon.grin.hu","mastodon.ml","midnightride.rs","milker.cafe","mobile.tmediatech.io","moon.holiday","mstdn.foxfam.club","mstdn.io","mstdn.starnix.network","mulmeyun.church","nazi.social","neckbeard.xyz","neenster.org","neko.ci","netzsphaere.xyz","newjack.city","nicecrew.digital","nnia.space","noagendasocial.com","norrebro.space","oursocialism.today","ovo.sc","pawoo.net","paypig.org","pedo.school","phreedom.tk","pieville.net","pkteerium.xyz","pl.murky.club","pl.spiderden.net","pl.tkammer.de","pl.zombiecats.run","pleroma.nobodyhasthe.biz","pleroma.runfox.tk","pleroma.site","plr.inferencium.net","pmth.us","poa.st","pod.vladtepesblog.com","political.icu","pooper.social","posting.lolicon.rocks","preteengirls.biz","prout.social","qoto.org","rage.lol","rakket.app","raplst.town","rdrama.cc","ryona.agency","s.sneak.berlin","seal.cafe","sealion.club","search.fedi.app","sementerrori.st","shitposter.club","shortstackran.ch","silkhe.art","sleepy.cafe","soc.mahodou.moe","soc.redeyes.site","social.076.ne.jp","social.anoxinon.de","social.chadland.net","social.freetalklive.com","social.getgle.org","social.handholding.io","social.headsca.la","social.imirhil.fr","social.lovingexpressions.net","social.manalejandro.com","social.midwaytrades.com","social.pseudo-whiskey.bar","social.targaryen.house","social.teci.world","societal.co","society.oftrolls.com","socks.pinnoto.org","socnet.supes.com","solagg.com","spinster.xyz","springbo.cc","stereophonic.space","sunshinegardens.org","theautisticinvestors.quest","thechad.zone","theduran.icu","theosis.church","toot.love","toots.alirezahayati.com","traboone.com","truthsocial.co.in","truthsocial.com","tuusin.misono-ya.info","tweety.icu","unbound.social","unsafe.space","varishangout.net","video.nobodyhasthe.biz","voicenews.icu","voluntaryism.club","waifu.social","weeaboo.space","whinge.town","wolfgirl.bar","workers.dev","wurm.host","xiii.ch","xn--p1abe3d.xn--80asehdb","yggdrasil.social","youjo.love"],"reject_deletes":[],"report_removal":[]},"mrf_simple_info":{"federated_timeline_removal":{"botsin.space":{"reason":"A lot of bot content"}},"media_nsfw":{"humblr.social":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"kinky.business":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"kinkyelephant.com":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"knzk.me":{"reason":"Unmarked nsfw media"},"mstdn.jp":{"reason":"Not sure about the media policy"},"rubber.social":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"sinblr.com":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"switter.at":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"vipgirlfriend.xxx":{"reason":"Unmarked nsfw media"},"wxw.moe":{"reason":"Unmarked nsfw media"}}},"quarantined_instances":[],"quarantined_instances_info":{"quarantined_instances":{}}},"fields_limits":{"max_fields":10,"max_remote_fields":20,"name_length":512,"value_length":2048},"post_formats":["text/plain","text/html","text/markdown","text/bbcode","text/x.misskeymarkdown"],"privileged_staff":false},"stats":{"mau":1},"vapid_public_key":"BMg4q-rT3rkMzc29F7OS5uM6t-Rx4HncMIB1NXrKwNlVRfX-W1kwgOuq5pDy-WhWmOZudaegftjBTCX3-pzdDFc"},"poll_limits":{"max_expiration":31536000,"max_option_chars":200,"max_options":20,"min_expiration":0},"registrations":"FALSE","shout_limit":5000,"stats":{"domain_count":1035,"status_count":7,"user_count":1},"thumbnail":"https://soc.hyena.network/instance/thumbnail.jpeg","title":"HyNET Social","upload_limit":16000000,"uri":"https://soc.hyena.network","urls":{"streaming_api":"wss://soc.hyena.network"},"version":"2.7.2 (compatible; Akkoma 3.0.0)"}"#;
+    const ASONIX_INSTANCE: &str = r#"{"uri":"masto.asonix.dog","title":"asonix.dog","short_description":"The asonix of furry mastodon. For me and a few friends. DM me somewhere if u want an account lol","description":"A mastodon server that's only for me and nobody else sorry","email":"asonix@asonix.dog","version":"4.0.0rc2-asonix-changes","urls":{"streaming_api":"wss://masto.asonix.dog"},"stats":{"user_count":7,"status_count":12328,"domain_count":5146},"thumbnail":"https://masto.asonix.dog/system/site_uploads/files/000/000/002/@1x/32f51462a2b2bf2d.png","languages":["dog"],"registrations":false,"approval_required":false,"invites_enabled":false,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":{"id":"1","username":"asonix","acct":"asonix","display_name":"Liom on Mane :antiverified:","locked":true,"bot":false,"discoverable":true,"group":false,"created_at":"2021-02-09T00:00:00.000Z","note":"\u003cp\u003e26, local liom, friend, rust (lang) stan, bi \u003c/p\u003e\u003cp\u003eicon by \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://furaffinity.net/user/lalupine\" target=\"blank\" rel=\"noopener noreferrer\" class=\"u-url mention\"\u003e@\u003cspan\u003elalupine@furaffinity.net\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003cbr /\u003eheader by \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://furaffinity.net/user/tronixx\" target=\"blank\" rel=\"noopener noreferrer\" class=\"u-url mention\"\u003e@\u003cspan\u003etronixx@furaffinity.net\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003eTestimonials:\u003c/p\u003e\u003cp\u003eStand: LIONS\u003cbr /\u003eStand User: AODE\u003cbr /\u003e- Keris (not on here)\u003c/p\u003e","url":"https://masto.asonix.dog/@asonix","avatar":"https://masto.asonix.dog/system/accounts/avatars/000/000/001/original/00852df0e6fee7e0.png","avatar_static":"https://masto.asonix.dog/system/accounts/avatars/000/000/001/original/00852df0e6fee7e0.png","header":"https://masto.asonix.dog/system/accounts/headers/000/000/001/original/8122ce3e5a745385.png","header_static":"https://masto.asonix.dog/system/accounts/headers/000/000/001/original/8122ce3e5a745385.png","followers_count":237,"following_count":474,"statuses_count":8798,"last_status_at":"2022-11-08","noindex":true,"emojis":[{"shortcode":"antiverified","url":"https://masto.asonix.dog/system/custom_emojis/images/000/030/053/original/bb0bc2e395b9a127.png","static_url":"https://masto.asonix.dog/system/custom_emojis/images/000/030/053/static/bb0bc2e395b9a127.png","visible_in_picker":true}],"fields":[{"name":"pronouns","value":"he/they","verified_at":null},{"name":"software","value":"bad","verified_at":null},{"name":"gitea","value":"\u003ca href=\"https://git.asonix.dog\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003egit.asonix.dog\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":null},{"name":"join my","value":"relay","verified_at":null}]},"rules":[]}"#;
+    const HYNET_INSTANCE: &str = r#"{"approval_required":false,"avatar_upload_limit":2000000,"background_image":"https://soc.hyena.network/images/city.jpg","background_upload_limit":4000000,"banner_upload_limit":4000000,"description":"Akkoma: The cooler fediverse server","description_limit":5000,"email":"me@hyena.network","languages":["en"],"max_toot_chars":"5000","pleroma":{"metadata":{"account_activation_required":true,"features":["pleroma_api","mastodon_api","mastodon_api_streaming","polls","v2_suggestions","pleroma_explicit_addressing","shareable_emoji_packs","multifetch","pleroma:api/v1/notifications:include_types_filter","chat","shout","relay","safe_dm_mentions","pleroma_emoji_reactions","pleroma_chat_messages","exposable_reactions","profile_directory","custom_emoji_reactions"],"federation":{"enabled":true,"exclusions":false,"mrf_hashtag":{"federated_timeline_removal":[],"reject":[],"sensitive":["nsfw"]},"mrf_policies":["SimplePolicy","EnsureRePrepended","HashtagPolicy"],"mrf_simple":{"accept":[],"avatar_removal":[],"banner_removal":[],"federated_timeline_removal":["botsin.space"],"followers_only":[],"media_nsfw":["mstdn.jp","wxw.moe","knzk.me","vipgirlfriend.xxx","humblr.social","switter.at","kinkyelephant.com","sinblr.com","kinky.business","rubber.social"],"media_removal":[],"reject":["*.10minutepleroma.com","101010.pl","13bells.com","2.distsn.org","2hu.club","2ndamendment.social","434.earth","4chan.icu","4qq.org","7td.org","80percent.social","a.nti.social","aaathats3as.com","accela.online","amala.schwartzwelt.xyz","angrytoday.com","anime.website","antitwitter.moe","antivaxxer.icu","archivefedifor.fun","artalley.social","bae.st","bajax.us","baraag.net","bbs.kawa-kun.com","beefyboys.club","beefyboys.win","bikeshed.party","bitcoinhackers.org","bleepp.com","blovice.bahnhof.cz","brighteon.social","buildthatwallandmakeamericagreatagain.trumpislovetrumpis.life","bungle.online","cawfee.club","censorship.icu","chungus.cc","club.darknight-coffee.org","clubcyberia.co","cock.fish","cock.li","comfyboy.club","contrapointsfan.club","coon.town","counter.social","cum.salon","d-fens.systems","definitely-not-archivefedifor.fun","degenerates.fail","desuposter.club","detroitriotcity.com","developer.gab.com","dogwhipping.day","eientei.org","enigmatic.observer","eveningzoo.club","exited.eu","federation.krowverse.services","fedi.cc","fedi.krowverse.services","fedi.pawlicker.com","fedi.vern.cc","freak.university","freeatlantis.com","freecumextremist.com","freesoftwareextremist.com","freespeech.firedragonstudios.com","freespeech.host","freespeechextremist.com","freevoice.space","freezepeach.xyz","froth.zone","fuckgov.org","gab.ai","gab.polaris-1.work","gab.protohype.net","gabfed.com","gameliberty.club","gearlandia.haus","gitmo.life","glindr.org","glittersluts.xyz","glowers.club","godspeed.moe","gorf.pub","goyim.app","gs.kawa-kun.com","hagra.net","hallsofamenti.io","hayu.sh","hentai.baby","honkwerx.tech","hunk.city","husk.site","iddqd.social","ika.moe","isexychat.space","jaeger.website","justicewarrior.social","kag.social","katiehopkinspolitical.icu","kiwifarms.cc","kiwifarms.is","kiwifarms.net","kohrville.net","koyu.space","kys.moe","lain.com","lain.sh","leafposter.club","lets.saynoto.lgbt","liberdon.com","libertarianism.club","ligma.pro","lolis.world","masochi.st","masthead.social","mastodon.digitalsuccess.dev","mastodon.fidonet.io","mastodon.grin.hu","mastodon.ml","midnightride.rs","milker.cafe","mobile.tmediatech.io","moon.holiday","mstdn.foxfam.club","mstdn.io","mstdn.starnix.network","mulmeyun.church","nazi.social","neckbeard.xyz","neenster.org","neko.ci","netzsphaere.xyz","newjack.city","nicecrew.digital","nnia.space","noagendasocial.com","norrebro.space","oursocialism.today","ovo.sc","pawoo.net","paypig.org","pedo.school","phreedom.tk","pieville.net","pkteerium.xyz","pl.murky.club","pl.spiderden.net","pl.tkammer.de","pl.zombiecats.run","pleroma.nobodyhasthe.biz","pleroma.runfox.tk","pleroma.site","plr.inferencium.net","pmth.us","poa.st","pod.vladtepesblog.com","political.icu","pooper.social","posting.lolicon.rocks","preteengirls.biz","prout.social","qoto.org","rage.lol","rakket.app","raplst.town","rdrama.cc","ryona.agency","s.sneak.berlin","seal.cafe","sealion.club","search.fedi.app","sementerrori.st","shitposter.club","shortstackran.ch","silkhe.art","sleepy.cafe","soc.mahodou.moe","soc.redeyes.site","social.076.ne.jp","social.anoxinon.de","social.chadland.net","social.freetalklive.com","social.getgle.org","social.handholding.io","social.headsca.la","social.imirhil.fr","social.lovingexpressions.net","social.manalejandro.com","social.midwaytrades.com","social.pseudo-whiskey.bar","social.targaryen.house","social.teci.world","societal.co","society.oftrolls.com","socks.pinnoto.org","socnet.supes.com","solagg.com","spinster.xyz","springbo.cc","stereophonic.space","sunshinegardens.org","theautisticinvestors.quest","thechad.zone","theduran.icu","theosis.church","toot.love","toots.alirezahayati.com","traboone.com","truthsocial.co.in","truthsocial.com","tuusin.misono-ya.info","tweety.icu","unbound.social","unsafe.space","varishangout.net","video.nobodyhasthe.biz","voicenews.icu","voluntaryism.club","waifu.social","weeaboo.space","whinge.town","wolfgirl.bar","workers.dev","wurm.host","xiii.ch","xn--p1abe3d.xn--80asehdb","yggdrasil.social","youjo.love"],"reject_deletes":[],"report_removal":[]},"mrf_simple_info":{"federated_timeline_removal":{"botsin.space":{"reason":"A lot of bot content"}},"media_nsfw":{"humblr.social":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"kinky.business":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"kinkyelephant.com":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"knzk.me":{"reason":"Unmarked nsfw media"},"mstdn.jp":{"reason":"Not sure about the media policy"},"rubber.social":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"sinblr.com":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"switter.at":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"vipgirlfriend.xxx":{"reason":"Unmarked nsfw media"},"wxw.moe":{"reason":"Unmarked nsfw media"}}},"quarantined_instances":[],"quarantined_instances_info":{"quarantined_instances":{}}},"fields_limits":{"max_fields":10,"max_remote_fields":20,"name_length":512,"value_length":2048},"post_formats":["text/plain","text/html","text/markdown","text/bbcode","text/x.misskeymarkdown"],"privileged_staff":false},"stats":{"mau":1},"vapid_public_key":"BMg4q-rT3rkMzc29F7OS5uM6t-Rx4HncMIB1NXrKwNlVRfX-W1kwgOuq5pDy-WhWmOZudaegftjBTCX3-pzdDFc"},"poll_limits":{"max_expiration":31536000,"max_option_chars":200,"max_options":20,"min_expiration":0},"registrations":"FALSE","shout_limit":5000,"stats":{"domain_count":1035,"status_count":7,"user_count":1},"thumbnail":"https://soc.hyena.network/instance/thumbnail.jpeg","title":"HyNET Social","upload_limit":16000000,"uri":"https://soc.hyena.network","urls":{"streaming_api":"wss://soc.hyena.network"},"version":"2.7.2 (compatible; Akkoma 3.0.0)"}"#;
 
     #[test]
     fn deser_masto_instance_with_contact() {
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index 21d5b06..8166fda 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -159,10 +159,10 @@ mod tests {
     use crate::apub::AcceptedActors;
     use rsa::{pkcs8::DecodePublicKey, RsaPublicKey};
 
-    const ASONIX_DOG_ACTOR: &'static str = r#"{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","toot":"http://joinmastodon.org/ns#","featured":{"@id":"toot:featured","@type":"@id"},"featuredTags":{"@id":"toot:featuredTags","@type":"@id"},"alsoKnownAs":{"@id":"as:alsoKnownAs","@type":"@id"},"movedTo":{"@id":"as:movedTo","@type":"@id"},"schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value","discoverable":"toot:discoverable","Device":"toot:Device","Ed25519Signature":"toot:Ed25519Signature","Ed25519Key":"toot:Ed25519Key","Curve25519Key":"toot:Curve25519Key","EncryptedMessage":"toot:EncryptedMessage","publicKeyBase64":"toot:publicKeyBase64","deviceId":"toot:deviceId","claim":{"@type":"@id","@id":"toot:claim"},"fingerprintKey":{"@type":"@id","@id":"toot:fingerprintKey"},"identityKey":{"@type":"@id","@id":"toot:identityKey"},"devices":{"@type":"@id","@id":"toot:devices"},"messageFranking":"toot:messageFranking","messageType":"toot:messageType","cipherText":"toot:cipherText","suspended":"toot:suspended"}],"id":"https://masto.asonix.dog/actor","type":"Application","inbox":"https://masto.asonix.dog/actor/inbox","outbox":"https://masto.asonix.dog/actor/outbox","preferredUsername":"masto.asonix.dog","url":"https://masto.asonix.dog/about/more?instance_actor=true","manuallyApprovesFollowers":true,"publicKey":{"id":"https://masto.asonix.dog/actor#main-key","owner":"https://masto.asonix.dog/actor","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx8zXS0QNg9YGUBsxAOBH\nJaxIn7i6t+Z4UOpSFDVa2kP0NvQgIJsq3wzRqvaiuncRWpkyFk1fTakiRGD32xnY\nt+juuAaIBlU8eswKyANFqhcLAvFHmT3rA1848M4/YM19djvlL/PR9T53tPNHU+el\nS9MlsG3o6Zsj8YaUJtCI8RgEuJoROLHUb/V9a3oMQ7CfuIoSvF3VEz3/dRT09RW6\n0wQX7yhka9WlKuayWLWmTcB9lAIX6neBk+qKc8VSEsO7mHkzB8mRgVcS2uYZl1eA\nD8/jTT+SlpeFNDZk0Oh35GNFoOxh9qjRw3NGxu7jJCVBehDODzasOv4xDxKAhONa\njQIDAQAB\n-----END PUBLIC KEY-----\n"},"endpoints":{"sharedInbox":"https://masto.asonix.dog/inbox"}}"#;
-    const KARJALAZET_RELAY: &'static str = r#"{"@context":["https://www.w3.org/ns/activitystreams","https://pleroma.karjalazet.se/schemas/litepub-0.1.jsonld",{"@language":"und"}],"alsoKnownAs":[],"attachment":[],"capabilities":{},"discoverable":false,"endpoints":{"oauthAuthorizationEndpoint":"https://pleroma.karjalazet.se/oauth/authorize","oauthRegistrationEndpoint":"https://pleroma.karjalazet.se/api/v1/apps","oauthTokenEndpoint":"https://pleroma.karjalazet.se/oauth/token","sharedInbox":"https://pleroma.karjalazet.se/inbox","uploadMedia":"https://pleroma.karjalazet.se/api/ap/upload_media"},"featured":"https://pleroma.karjalazet.se/relay/collections/featured","followers":"https://pleroma.karjalazet.se/relay/followers","following":"https://pleroma.karjalazet.se/relay/following","id":"https://pleroma.karjalazet.se/relay","inbox":"https://pleroma.karjalazet.se/relay/inbox","manuallyApprovesFollowers":false,"name":null,"outbox":"https://pleroma.karjalazet.se/relay/outbox","preferredUsername":"relay","publicKey":{"id":"https://pleroma.karjalazet.se/relay#main-key","owner":"https://pleroma.karjalazet.se/relay","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAucoyCht6QpEzUPdQWP/J\nJYxObSH3MCcXBnG4d0OX78QshloeAHhl78EZ5c8I0ePmIjDg2NFK3/pG0EvSrHe2\nIZHnHaN5emgCb2ifNya5W572yfQXo1tUQy+ZXtbTUA7BWbr4LuCvd+HUavMwbx72\neraSZTiQj//ObwpbXFoZO5I/+e5avGmVnfmr/y2cG95hqFDtI3438RgZyBjY5kJM\nY1MLWoY9itGSfYmBtxRj3umlC2bPuBB+hHUJi6TvP7NO6zuUZ66m4ETyuBDi8iP6\ngnUp3Q4+1/I3nDUmhjt7OXckUcX3r5M4UHD3VVUFG0aZw6WWMEAxlyFf/07fCkhR\nBwIDAQAB\n-----END PUBLIC KEY-----\n\n"},"summary":"","tag":[],"type":"Person","url":"https://pleroma.karjalazet.se/relay"}"#;
-    const ASONIX_DOG_KEY: &'static str = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx8zXS0QNg9YGUBsxAOBH\nJaxIn7i6t+Z4UOpSFDVa2kP0NvQgIJsq3wzRqvaiuncRWpkyFk1fTakiRGD32xnY\nt+juuAaIBlU8eswKyANFqhcLAvFHmT3rA1848M4/YM19djvlL/PR9T53tPNHU+el\nS9MlsG3o6Zsj8YaUJtCI8RgEuJoROLHUb/V9a3oMQ7CfuIoSvF3VEz3/dRT09RW6\n0wQX7yhka9WlKuayWLWmTcB9lAIX6neBk+qKc8VSEsO7mHkzB8mRgVcS2uYZl1eA\nD8/jTT+SlpeFNDZk0Oh35GNFoOxh9qjRw3NGxu7jJCVBehDODzasOv4xDxKAhONa\njQIDAQAB\n-----END PUBLIC KEY-----\n";
-    const KARJALAZET_KEY: &'static str = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAucoyCht6QpEzUPdQWP/J\nJYxObSH3MCcXBnG4d0OX78QshloeAHhl78EZ5c8I0ePmIjDg2NFK3/pG0EvSrHe2\nIZHnHaN5emgCb2ifNya5W572yfQXo1tUQy+ZXtbTUA7BWbr4LuCvd+HUavMwbx72\neraSZTiQj//ObwpbXFoZO5I/+e5avGmVnfmr/y2cG95hqFDtI3438RgZyBjY5kJM\nY1MLWoY9itGSfYmBtxRj3umlC2bPuBB+hHUJi6TvP7NO6zuUZ66m4ETyuBDi8iP6\ngnUp3Q4+1/I3nDUmhjt7OXckUcX3r5M4UHD3VVUFG0aZw6WWMEAxlyFf/07fCkhR\nBwIDAQAB\n-----END PUBLIC KEY-----\n\n";
+    const ASONIX_DOG_ACTOR: &str = r#"{"@context":["https://www.w3.org/ns/activitystreams","https://w3id.org/security/v1",{"manuallyApprovesFollowers":"as:manuallyApprovesFollowers","toot":"http://joinmastodon.org/ns#","featured":{"@id":"toot:featured","@type":"@id"},"featuredTags":{"@id":"toot:featuredTags","@type":"@id"},"alsoKnownAs":{"@id":"as:alsoKnownAs","@type":"@id"},"movedTo":{"@id":"as:movedTo","@type":"@id"},"schema":"http://schema.org#","PropertyValue":"schema:PropertyValue","value":"schema:value","discoverable":"toot:discoverable","Device":"toot:Device","Ed25519Signature":"toot:Ed25519Signature","Ed25519Key":"toot:Ed25519Key","Curve25519Key":"toot:Curve25519Key","EncryptedMessage":"toot:EncryptedMessage","publicKeyBase64":"toot:publicKeyBase64","deviceId":"toot:deviceId","claim":{"@type":"@id","@id":"toot:claim"},"fingerprintKey":{"@type":"@id","@id":"toot:fingerprintKey"},"identityKey":{"@type":"@id","@id":"toot:identityKey"},"devices":{"@type":"@id","@id":"toot:devices"},"messageFranking":"toot:messageFranking","messageType":"toot:messageType","cipherText":"toot:cipherText","suspended":"toot:suspended"}],"id":"https://masto.asonix.dog/actor","type":"Application","inbox":"https://masto.asonix.dog/actor/inbox","outbox":"https://masto.asonix.dog/actor/outbox","preferredUsername":"masto.asonix.dog","url":"https://masto.asonix.dog/about/more?instance_actor=true","manuallyApprovesFollowers":true,"publicKey":{"id":"https://masto.asonix.dog/actor#main-key","owner":"https://masto.asonix.dog/actor","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx8zXS0QNg9YGUBsxAOBH\nJaxIn7i6t+Z4UOpSFDVa2kP0NvQgIJsq3wzRqvaiuncRWpkyFk1fTakiRGD32xnY\nt+juuAaIBlU8eswKyANFqhcLAvFHmT3rA1848M4/YM19djvlL/PR9T53tPNHU+el\nS9MlsG3o6Zsj8YaUJtCI8RgEuJoROLHUb/V9a3oMQ7CfuIoSvF3VEz3/dRT09RW6\n0wQX7yhka9WlKuayWLWmTcB9lAIX6neBk+qKc8VSEsO7mHkzB8mRgVcS2uYZl1eA\nD8/jTT+SlpeFNDZk0Oh35GNFoOxh9qjRw3NGxu7jJCVBehDODzasOv4xDxKAhONa\njQIDAQAB\n-----END PUBLIC KEY-----\n"},"endpoints":{"sharedInbox":"https://masto.asonix.dog/inbox"}}"#;
+    const KARJALAZET_RELAY: &str = r#"{"@context":["https://www.w3.org/ns/activitystreams","https://pleroma.karjalazet.se/schemas/litepub-0.1.jsonld",{"@language":"und"}],"alsoKnownAs":[],"attachment":[],"capabilities":{},"discoverable":false,"endpoints":{"oauthAuthorizationEndpoint":"https://pleroma.karjalazet.se/oauth/authorize","oauthRegistrationEndpoint":"https://pleroma.karjalazet.se/api/v1/apps","oauthTokenEndpoint":"https://pleroma.karjalazet.se/oauth/token","sharedInbox":"https://pleroma.karjalazet.se/inbox","uploadMedia":"https://pleroma.karjalazet.se/api/ap/upload_media"},"featured":"https://pleroma.karjalazet.se/relay/collections/featured","followers":"https://pleroma.karjalazet.se/relay/followers","following":"https://pleroma.karjalazet.se/relay/following","id":"https://pleroma.karjalazet.se/relay","inbox":"https://pleroma.karjalazet.se/relay/inbox","manuallyApprovesFollowers":false,"name":null,"outbox":"https://pleroma.karjalazet.se/relay/outbox","preferredUsername":"relay","publicKey":{"id":"https://pleroma.karjalazet.se/relay#main-key","owner":"https://pleroma.karjalazet.se/relay","publicKeyPem":"-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAucoyCht6QpEzUPdQWP/J\nJYxObSH3MCcXBnG4d0OX78QshloeAHhl78EZ5c8I0ePmIjDg2NFK3/pG0EvSrHe2\nIZHnHaN5emgCb2ifNya5W572yfQXo1tUQy+ZXtbTUA7BWbr4LuCvd+HUavMwbx72\neraSZTiQj//ObwpbXFoZO5I/+e5avGmVnfmr/y2cG95hqFDtI3438RgZyBjY5kJM\nY1MLWoY9itGSfYmBtxRj3umlC2bPuBB+hHUJi6TvP7NO6zuUZ66m4ETyuBDi8iP6\ngnUp3Q4+1/I3nDUmhjt7OXckUcX3r5M4UHD3VVUFG0aZw6WWMEAxlyFf/07fCkhR\nBwIDAQAB\n-----END PUBLIC KEY-----\n\n"},"summary":"","tag":[],"type":"Person","url":"https://pleroma.karjalazet.se/relay"}"#;
+    const ASONIX_DOG_KEY: &str = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx8zXS0QNg9YGUBsxAOBH\nJaxIn7i6t+Z4UOpSFDVa2kP0NvQgIJsq3wzRqvaiuncRWpkyFk1fTakiRGD32xnY\nt+juuAaIBlU8eswKyANFqhcLAvFHmT3rA1848M4/YM19djvlL/PR9T53tPNHU+el\nS9MlsG3o6Zsj8YaUJtCI8RgEuJoROLHUb/V9a3oMQ7CfuIoSvF3VEz3/dRT09RW6\n0wQX7yhka9WlKuayWLWmTcB9lAIX6neBk+qKc8VSEsO7mHkzB8mRgVcS2uYZl1eA\nD8/jTT+SlpeFNDZk0Oh35GNFoOxh9qjRw3NGxu7jJCVBehDODzasOv4xDxKAhONa\njQIDAQAB\n-----END PUBLIC KEY-----\n";
+    const KARJALAZET_KEY: &str = "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAucoyCht6QpEzUPdQWP/J\nJYxObSH3MCcXBnG4d0OX78QshloeAHhl78EZ5c8I0ePmIjDg2NFK3/pG0EvSrHe2\nIZHnHaN5emgCb2ifNya5W572yfQXo1tUQy+ZXtbTUA7BWbr4LuCvd+HUavMwbx72\neraSZTiQj//ObwpbXFoZO5I/+e5avGmVnfmr/y2cG95hqFDtI3438RgZyBjY5kJM\nY1MLWoY9itGSfYmBtxRj3umlC2bPuBB+hHUJi6TvP7NO6zuUZ66m4ETyuBDi8iP6\ngnUp3Q4+1/I3nDUmhjt7OXckUcX3r5M4UHD3VVUFG0aZw6WWMEAxlyFf/07fCkhR\nBwIDAQAB\n-----END PUBLIC KEY-----\n\n";
 
     #[test]
     fn handles_masto_keys() {

From 5d69eaf2abe39b4a84635154b8dc8e9af3741e0b Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 10:46:58 -0600
Subject: [PATCH 16/87] Add note about Add activity to README

---
 README.md | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/README.md b/README.md
index 64d873e..0caa05c 100644
--- a/README.md
+++ b/README.md
@@ -171,6 +171,9 @@ example, if the server is `https://relay.my.tld`, the correct URL would be
 - Update {anything}, the Update {anything} is relayed verbatim to listening servers
     Note that this activity will likely be rejected by the listening servers unless it has been
     signed with a JSON-LD signature
+- Add {anything}, the Add {anything} is relayed verbatim to listening servers
+    Note that this activity will likely be rejected by the listening servers unless it has been
+    signed with a JSON-LD signature
 
 ### Supported Discovery Protocols
 - Webfinger

From c15f591bc80588d338d0a339109df02766073946 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 10:56:25 -0600
Subject: [PATCH 17/87] Add punctuation to readme

---
 README.md | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index 0caa05c..ff02880 100644
--- a/README.md
+++ b/README.md
@@ -165,13 +165,13 @@ example, if the server is `https://relay.my.tld`, the correct URL would be
 - Follow Public, become a listener of the relay
 - Undo Follow {self-actor}, stop listening on the relay, an Undo Follow will be sent back
 - Undo Follow Public, stop listening on the relay
-- Delete {anything}, the Delete {anything} is relayed verbatim to listening servers
+- Delete {anything}, the Delete {anything} is relayed verbatim to listening servers.
     Note that this activity will likely be rejected by the listening servers unless it has been
     signed with a JSON-LD signature
-- Update {anything}, the Update {anything} is relayed verbatim to listening servers
+- Update {anything}, the Update {anything} is relayed verbatim to listening servers.
     Note that this activity will likely be rejected by the listening servers unless it has been
     signed with a JSON-LD signature
-- Add {anything}, the Add {anything} is relayed verbatim to listening servers
+- Add {anything}, the Add {anything} is relayed verbatim to listening servers.
     Note that this activity will likely be rejected by the listening servers unless it has been
     signed with a JSON-LD signature
 

From 430ebec81068a2d4681b2a8119211bafbe0816db Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 23:36:40 -0600
Subject: [PATCH 18/87] Improve tracing, immediately stringify spantrace,
 remove join macros

---
 src/config.rs          |  1 -
 src/data/actor.rs      | 12 ++++--------
 src/data/node.rs       |  8 +++-----
 src/error.rs           |  4 ++--
 src/extractors.rs      | 16 ++++++++--------
 src/routes/inbox.rs    |  8 +++-----
 src/routes/nodeinfo.rs | 16 ++++++++--------
 src/routes/statics.rs  |  2 +-
 8 files changed, 29 insertions(+), 38 deletions(-)

diff --git a/src/config.rs b/src/config.rs
index 61aa7a9..957cbc8 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -396,7 +396,6 @@ impl Config {
         self.do_generate_url(kind).expect("Generated valid IRI")
     }
 
-    #[tracing::instrument(level = "debug", skip_all, fields(base_uri = tracing::field::debug(&self.base_uri), kind = tracing::field::debug(&kind)))]
     fn do_generate_url(&self, kind: UrlKind) -> Result<IriString, Error> {
         let iri = match kind {
             UrlKind::Activity => FixedBaseResolver::new(self.base_uri.as_ref())
diff --git a/src/data/actor.rs b/src/data/actor.rs
index c0b3ddd..784e99f 100644
--- a/src/data/actor.rs
+++ b/src/data/actor.rs
@@ -37,7 +37,7 @@ impl ActorCache {
         ActorCache { db }
     }
 
-    #[tracing::instrument(level = "debug" name = "Get Actor", skip_all, fields(id = id.to_string().as_str(), requests))]
+    #[tracing::instrument(level = "debug" name = "Get Actor", skip_all, fields(id = id.to_string().as_str()))]
     pub(crate) async fn get(
         &self,
         id: &IriString,
@@ -56,12 +56,8 @@ impl ActorCache {
 
     #[tracing::instrument(level = "debug", name = "Add Connection", skip(self))]
     pub(crate) async fn add_connection(&self, actor: Actor) -> Result<(), Error> {
-        let add_connection = self.db.add_connection(actor.id.clone());
-        let save_actor = self.db.save_actor(actor);
-
-        tokio::try_join!(add_connection, save_actor)?;
-
-        Ok(())
+        self.db.add_connection(actor.id.clone()).await?;
+        self.db.save_actor(actor).await
     }
 
     #[tracing::instrument(level = "debug", name = "Remove Connection", skip(self))]
@@ -69,7 +65,7 @@ impl ActorCache {
         self.db.remove_connection(actor.id.clone()).await
     }
 
-    #[tracing::instrument(level = "debug", name = "Fetch remote actor", skip_all, fields(id = id.to_string().as_str(), requests))]
+    #[tracing::instrument(level = "debug", name = "Fetch remote actor", skip_all, fields(id = id.to_string().as_str()))]
     pub(crate) async fn get_no_cache(
         &self,
         id: &IriString,
diff --git a/src/data/node.rs b/src/data/node.rs
index 815cc7c..4ba6eb5 100644
--- a/src/data/node.rs
+++ b/src/data/node.rs
@@ -36,11 +36,9 @@ impl NodeCache {
 
     #[tracing::instrument(level = "debug", name = "Get nodes", skip(self))]
     pub(crate) async fn nodes(&self) -> Result<Vec<Node>, Error> {
-        let infos = self.db.connected_info();
-        let instances = self.db.connected_instance();
-        let contacts = self.db.connected_contact();
-
-        let (infos, instances, contacts) = tokio::try_join!(infos, instances, contacts)?;
+        let infos = self.db.connected_info().await?;
+        let instances = self.db.connected_instance().await?;
+        let contacts = self.db.connected_contact().await?;
 
         let vec = self
             .db
diff --git a/src/error.rs b/src/error.rs
index f399ebe..98df5c9 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -10,7 +10,7 @@ use std::{convert::Infallible, fmt::Debug, io};
 use tracing_error::SpanTrace;
 
 pub(crate) struct Error {
-    context: SpanTrace,
+    context: String,
     kind: ErrorKind,
 }
 
@@ -53,7 +53,7 @@ where
 {
     fn from(error: T) -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: error.into(),
         }
     }
diff --git a/src/extractors.rs b/src/extractors.rs
index 572da34..f56b9af 100644
--- a/src/extractors.rs
+++ b/src/extractors.rs
@@ -80,7 +80,7 @@ impl Admin {
 #[derive(Debug, thiserror::Error)]
 #[error("Failed authentication")]
 pub(crate) struct Error {
-    context: SpanTrace,
+    context: String,
     #[source]
     kind: ErrorKind,
 }
@@ -88,49 +88,49 @@ pub(crate) struct Error {
 impl Error {
     fn invalid() -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::Invalid,
         }
     }
 
     fn missing_config() -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::MissingConfig,
         }
     }
 
     fn missing_db() -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::MissingDb,
         }
     }
 
     fn bcrypt_verify(e: BcryptError) -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::BCryptVerify(e),
         }
     }
 
     fn bcrypt_hash(e: BcryptError) -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::BCryptHash(e),
         }
     }
 
     fn parse_header(e: ParseError) -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::ParseHeader(e),
         }
     }
 
     fn canceled(_: BlockingError) -> Self {
         Error {
-            context: SpanTrace::capture(),
+            context: SpanTrace::capture().to_string(),
             kind: ErrorKind::Canceled,
         }
     }
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 38d492a..b4db18d 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -36,10 +36,8 @@ pub(crate) async fn route(
         .await?
         .into_inner();
 
-    let is_allowed = state.db.is_allowed(actor.id.clone());
-    let is_connected = state.db.is_connected(actor.id.clone());
-
-    let (is_allowed, is_connected) = tokio::try_join!(is_allowed, is_connected)?;
+    let is_allowed = state.db.is_allowed(actor.id.clone()).await?;
+    let is_connected = state.db.is_connected(actor.id.clone()).await?;
 
     if !is_allowed {
         return Err(ErrorKind::NotAllowed(actor.id.to_string()).into());
@@ -54,7 +52,7 @@ pub(crate) async fn route(
     } else if config.validate_signatures() {
         if let Some((verified, _)) = verified {
             if actor.public_key_id.as_str() != verified.key_id() {
-                tracing::error!("Bad actor, more info: {:?}", input);
+                tracing::error!("Actor signed with wrong key");
                 return Err(ErrorKind::BadActor(
                     actor.public_key_id.to_string(),
                     verified.key_id().to_owned(),
diff --git a/src/routes/nodeinfo.rs b/src/routes/nodeinfo.rs
index 18b1c3a..a504496 100644
--- a/src/routes/nodeinfo.rs
+++ b/src/routes/nodeinfo.rs
@@ -24,18 +24,18 @@ struct Links {
     links: Vec<Link>,
 }
 
-#[tracing::instrument(name = "NodeInfo")]
+#[tracing::instrument(name = "NodeInfo", skip_all)]
 pub(crate) async fn route(
     config: web::Data<Config>,
     state: web::Data<State>,
 ) -> web::Json<NodeInfo> {
-    let (inboxes, blocks) = tokio::join!(state.db.inboxes(), async {
-        if config.publish_blocks() {
-            Some(state.db.blocks().await.unwrap_or_default())
-        } else {
-            None
-        }
-    });
+    let inboxes = state.db.inboxes().await;
+
+    let blocks = if config.publish_blocks() {
+        Some(state.db.blocks().await.unwrap_or_default())
+    } else {
+        None
+    };
 
     let peers = inboxes
         .unwrap_or_default()
diff --git a/src/routes/statics.rs b/src/routes/statics.rs
index 31e37c1..6c7788a 100644
--- a/src/routes/statics.rs
+++ b/src/routes/statics.rs
@@ -5,7 +5,7 @@ use actix_web::{
 };
 
 #[allow(clippy::async_yields_async)]
-#[tracing::instrument(name = "Statistics")]
+#[tracing::instrument(name = "Statics")]
 pub(crate) async fn route(filename: web::Path<String>) -> HttpResponse {
     if let Some(data) = StaticFile::get(&filename.into_inner()) {
         HttpResponse::Ok()

From c5e254dad68b803006a538689ea35c80a3758c11 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 23:37:09 -0600
Subject: [PATCH 19/87] Update deps

---
 Cargo.lock | 32 +++++++++++---------------------
 1 file changed, 11 insertions(+), 21 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b658c15..ca2dea0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -378,15 +378,6 @@ version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
-[[package]]
-name = "async-mutex"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "479db852db25d9dbf6204e6cb6253698f175c15726470f78af0d918e99d6156e"
-dependencies = [
- "event-listener",
-]
-
 [[package]]
 name = "async-stream"
 version = "0.3.3"
@@ -517,13 +508,12 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-actix"
-version = "0.14.4"
+version = "0.14.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7a36626c73630619c8d044a4ee52336e283bc0cfa0f60b17c9ee0bd55dec455"
+checksum = "b6c7b21d56df90647f9bef717379663f8d92374f3707d95890a3e6da2f8a7359"
 dependencies = [
  "actix-rt",
  "anyhow",
- "async-mutex",
  "async-trait",
  "background-jobs-core",
  "metrics",
@@ -538,9 +528,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-core"
-version = "0.14.3"
+version = "0.14.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b102461c17491eb9ebf4fb974fa894cdc7516deada3cbdc0761a32e35f64322"
+checksum = "21825e3893be7b103cd52cf3ee65db388b35816b5ec1229032b342a334eef533"
 dependencies = [
  "actix-rt",
  "anyhow",
@@ -1603,9 +1593,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.1.3"
+version = "0.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f9f08d8963a6c613f4b1a78f4f4a4dbfadf8e6545b2d72861731e4858b8b47f"
+checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
 
 [[package]]
 name = "local-channel"
@@ -2110,7 +2100,7 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
 dependencies = [
  "instant",
  "lock_api",
- "parking_lot_core 0.8.5",
+ "parking_lot_core 0.8.6",
 ]
 
 [[package]]
@@ -2125,9 +2115,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.8.5"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
+checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc"
 dependencies = [
  "cfg-if",
  "instant",
@@ -2163,9 +2153,9 @@ dependencies = [
 
 [[package]]
 name = "paste"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1de2e551fb905ac83f73f7aedf2f0cb4a0da7e35efa24a202a936269f1f18e1"
+checksum = "cf1c2c742266c2f1041c914ba65355a83ae8747b05f208319784083583494b4b"
 
 [[package]]
 name = "pathdiff"

From 5968cb8953d578d700b999a2f321496dd2fc819e Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 23:40:53 -0600
Subject: [PATCH 20/87] bump deps

---
 Cargo.lock | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ca2dea0..cad2f91 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1333,9 +1333,9 @@ dependencies = [
 
 [[package]]
 name = "http-signature-normalization-actix"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60d41016e2fd353e0a3f266ca9ac9b9dbf439c4a2bede3b400ba7ea73ac9bb3f"
+checksum = "eabdd590b7b712a168bf4b01a63dc3118f668c3c5a76d0b9f2abf45c20dff55a"
 dependencies = [
  "actix-http",
  "actix-rt",

From 549eb472029bfdf1763c37150a4474fe15a98ba3 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 13 Dec 2022 23:41:06 -0600
Subject: [PATCH 21/87] Bump version

---
 Cargo.toml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Cargo.toml b/Cargo.toml
index 0efc9e0..e3cdaac 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.70"
+version = "0.3.71"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 178d23bcbd05b37b8216fe8cd71e666ff5a1b7b8 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Wed, 14 Dec 2022 20:17:14 -0600
Subject: [PATCH 22/87] Bump deps

---
 Cargo.lock | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index cad2f91..fb533d5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.70"
+version = "0.3.71"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
@@ -2326,9 +2326,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "0.3.16"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac662b3a6490de378b0ee15cf2dfff7127aebfe0b19acc65e7fbca3d299c3788"
+checksum = "3ef946e2f765276038550e74abfbda40c84d73278417c071e0f19f8af6ba100b"
 
 [[package]]
 name = "ppv-lite86"
@@ -3300,9 +3300,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.5.9"
+version = "0.5.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
+checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
 dependencies = [
  "serde",
 ]

From 886c7d0ac6d026063e36b373b2e5e9473cf3c54a Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 09:44:04 -0600
Subject: [PATCH 23/87] Apply patch from perallamint on github

Temporary fix: allow signing bypass for 410 gone actors
DIRTY FIX: implement sigcheck_bypass for 410'ing actors
---
 src/error.rs               |  4 ++++
 src/middleware/verifier.rs | 18 ++++++++++++++----
 src/routes/inbox.rs        | 18 +++++++++++++++---
 3 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/src/error.rs b/src/error.rs
index 98df5c9..141b25e 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -26,6 +26,10 @@ impl Error {
     pub(crate) fn is_bad_request(&self) -> bool {
         matches!(self.kind, ErrorKind::Status(_, StatusCode::BAD_REQUEST))
     }
+
+    pub(crate) fn is_gone(&self) -> bool {
+        matches!(self.kind, ErrorKind::Status(_, StatusCode::GONE))
+    }
 }
 
 impl std::fmt::Debug for Error {
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index 8166fda..6b201b0 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -65,11 +65,21 @@ impl MyVerify {
 
             actor_id
         } else {
-            self.0
+            match self
+                .0
                 .fetch::<PublicKeyResponse>(public_key_id.as_str())
-                .await?
-                .actor_id()
-                .ok_or(ErrorKind::MissingId)?
+                .await
+            {
+                Ok(res) => res.actor_id().ok_or(ErrorKind::MissingId),
+                Err(e) => {
+                    if e.is_gone() {
+                        tracing::warn!("Actor gone: {}, trusting it for now.", public_key_id);
+                        return Ok(true);
+                    } else {
+                        return Err(e);
+                    }
+                }
+            }?
         };
 
         // Previously we verified the sig from an actor's local cache
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index b4db18d..41c25f9 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -27,14 +27,26 @@ pub(crate) async fn route(
     verified: Option<(SignatureVerified, DigestVerified)>,
 ) -> Result<HttpResponse, Error> {
     let input = input.into_inner();
+    println!("ActivityActor: {:?}", input);
 
-    let actor = actors
+    let actor = match actors
         .get(
             input.actor()?.as_single_id().ok_or(ErrorKind::MissingId)?,
             &client,
         )
-        .await?
-        .into_inner();
+        .await
+    {
+        Ok(actor) => actor.into_inner(),
+        Err(e) => {
+            // Eat up the message if actor is 410 and message is delete
+            let kind = input.kind().ok_or(ErrorKind::MissingKind)?;
+            if e.is_gone() && *kind == ValidTypes::Delete {
+                return Ok(accepted(serde_json::json!({})));
+            } else {
+                return Err(e);
+            }
+        }
+    };
 
     let is_allowed = state.db.is_allowed(actor.id.clone()).await?;
     let is_connected = state.db.is_connected(actor.id.clone()).await?;

From b56bddccb4b7d9b0267bcc856d648fbc7b90db94 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 11:39:30 -0600
Subject: [PATCH 24/87] Allow Signature to be missing if kind is Delete, return
 early without additional processing

---
 Cargo.lock                 | 80 +++++++++++++++++++-------------------
 Cargo.toml                 |  2 +-
 src/config.rs              | 18 +--------
 src/error.rs               |  2 +-
 src/main.rs                | 10 ++---
 src/middleware/verifier.rs |  4 +-
 src/routes/inbox.rs        | 42 ++++++++++----------
 7 files changed, 71 insertions(+), 87 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index fb533d5..1d0816d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -292,9 +292,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.66"
+version = "1.0.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "216261ddc8289130e551ddcd5ce8a064710c0d064a4d2895c67151c92b5443f6"
+checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
@@ -401,9 +401,9 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.59"
+version = "0.1.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31e6e93155431f3931513b243d371981bb2770112b370c82745a1d19d2f99364"
+checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -663,9 +663,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.77"
+version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e9f73505338f7d905b19d18738976aae232eb46b8efc15554ffc56deb5d9ebe4"
+checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
 
 [[package]]
 name = "cfg-if"
@@ -1333,9 +1333,9 @@ dependencies = [
 
 [[package]]
 name = "http-signature-normalization-actix"
-version = "0.7.2"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eabdd590b7b712a168bf4b01a63dc3118f668c3c5a76d0b9f2abf45c20dff55a"
+checksum = "1dc95d9ca3b4e2f93a97e5ccf9f26992c69a272e0abad8807180f0a9e9b59e31"
 dependencies = [
  "actix-http",
  "actix-rt",
@@ -1521,9 +1521,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc"
+checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
 
 [[package]]
 name = "js-sys"
@@ -2153,9 +2153,9 @@ dependencies = [
 
 [[package]]
 name = "paste"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf1c2c742266c2f1041c914ba65355a83ae8747b05f208319784083583494b4b"
+checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
 
 [[package]]
 name = "pathdiff"
@@ -2326,9 +2326,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "0.3.17"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ef946e2f765276038550e74abfbda40c84d73278417c071e0f19f8af6ba100b"
+checksum = "81bdd679d533107e090c2704a35982fc06302e30898e63ffa26a81155c012e92"
 
 [[package]]
 name = "ppv-lite86"
@@ -2344,9 +2344,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "prettyplease"
-version = "0.1.21"
+version = "0.1.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c142c0e46b57171fe0c528bee8c5b7569e80f0c17e377cd0e30ea57dbc11bb51"
+checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773"
 dependencies = [
  "proc-macro2",
  "syn",
@@ -2378,9 +2378,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.47"
+version = "1.0.49"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5ea3d908b0e36316caf9e9e2c4625cdde190a7e6f440d794667ed17a1855e725"
+checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
 dependencies = [
  "unicode-ident",
 ]
@@ -2458,9 +2458,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.21"
+version = "1.0.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
+checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
 dependencies = [
  "proc-macro2",
 ]
@@ -2762,15 +2762,15 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.9"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
+checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
 
 [[package]]
 name = "ryu"
-version = "1.0.11"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
+checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
 
 [[package]]
 name = "scopeguard"
@@ -2790,24 +2790,24 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.14"
+version = "1.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4"
+checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
 
 [[package]]
 name = "serde"
-version = "1.0.150"
+version = "1.0.151"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e326c9ec8042f1b5da33252c8a37e9ffbd2c9bef0155215b6e6c80c790e05f91"
+checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.150"
+version = "1.0.151"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42a3df25b0713732468deadad63ab9da1f1fd75a48a15024b50363f128db627e"
+checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2816,9 +2816,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.89"
+version = "1.0.91"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db"
+checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
 dependencies = [
  "itoa",
  "ryu",
@@ -3014,9 +3014,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
-version = "1.0.105"
+version = "1.0.107"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908"
+checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3152,18 +3152,18 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.37"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e"
+checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.37"
+version = "1.0.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb"
+checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3562,9 +3562,9 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3"
+checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
 
 [[package]]
 name = "unicode-normalization"
diff --git a/Cargo.toml b/Cargo.toml
index e3cdaac..a3c3272 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -86,7 +86,7 @@ default-features = false
 features = ["background-jobs-actix", "error-logging"]
 
 [dependencies.http-signature-normalization-actix]
-version = "0.7.1"
+version = "0.8.0"
 default-features = false
 features = ["client", "server", "sha-2"]
 
diff --git a/src/config.rs b/src/config.rs
index 957cbc8..3a46833 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -1,9 +1,6 @@
 use crate::{
-    data::{ActorCache, State},
     error::Error,
     extractors::{AdminConfig, XApiToken},
-    middleware::MyVerify,
-    requests::Requests,
 };
 use activitystreams::{
     iri,
@@ -14,7 +11,7 @@ use activitystreams::{
     },
 };
 use config::Environment;
-use http_signature_normalization_actix::prelude::{VerifyDigest, VerifySignature};
+use http_signature_normalization_actix::prelude::VerifyDigest;
 use rustls::{Certificate, PrivateKey};
 use sha2::{Digest, Sha256};
 use std::{io::BufReader, net::IpAddr, path::PathBuf};
@@ -277,19 +274,6 @@ impl Config {
         }
     }
 
-    pub(crate) fn signature_middleware(
-        &self,
-        requests: Requests,
-        actors: ActorCache,
-        state: State,
-    ) -> VerifySignature<MyVerify> {
-        if self.validate_signatures {
-            VerifySignature::new(MyVerify(requests, actors, state), Default::default())
-        } else {
-            VerifySignature::new(MyVerify(requests, actors, state), Default::default()).optional()
-        }
-    }
-
     pub(crate) fn x_api_token(&self) -> Option<XApiToken> {
         self.api_token.clone().map(XApiToken::new)
     }
diff --git a/src/error.rs b/src/error.rs
index 141b25e..ece3c06 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -126,7 +126,7 @@ pub(crate) enum ErrorKind {
     BadActor(String, String),
 
     #[error("Signature verification is required, but no signature was given")]
-    NoSignature(String),
+    NoSignature(Option<String>),
 
     #[error("Wrong ActivityPub kind, {0}")]
     Kind(String),
diff --git a/src/main.rs b/src/main.rs
index f31f63c..5605a48 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -7,6 +7,7 @@ use actix_web::{middleware::Compress, web, App, HttpServer};
 use collector::MemoryCollector;
 #[cfg(feature = "console")]
 use console_subscriber::ConsoleLayer;
+use http_signature_normalization_actix::middleware::VerifySignature;
 use opentelemetry::{sdk::Resource, KeyValue};
 use opentelemetry_otlp::WithExportConfig;
 use rustls::ServerConfig;
@@ -36,7 +37,7 @@ use self::{
     data::{ActorCache, MediaCache, State},
     db::Db,
     jobs::create_workers,
-    middleware::{DebugPayload, RelayResolver, Timings},
+    middleware::{DebugPayload, MyVerify, RelayResolver, Timings},
     routes::{actor, inbox, index, nodeinfo, nodeinfo_meta, statics},
 };
 
@@ -232,10 +233,9 @@ async fn do_server_main(
             .service(
                 web::resource("/inbox")
                     .wrap(config.digest_middleware())
-                    .wrap(config.signature_middleware(
-                        state.requests(&config),
-                        actors.clone(),
-                        state.clone(),
+                    .wrap(VerifySignature::new(
+                        MyVerify(state.requests(&config), actors.clone(), state.clone()),
+                        Default::default(),
                     ))
                     .wrap(DebugPayload(config.debug()))
                     .route(web::post().to(inbox)),
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index 6b201b0..a982563 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -73,8 +73,8 @@ impl MyVerify {
                 Ok(res) => res.actor_id().ok_or(ErrorKind::MissingId),
                 Err(e) => {
                     if e.is_gone() {
-                        tracing::warn!("Actor gone: {}, trusting it for now.", public_key_id);
-                        return Ok(true);
+                        tracing::warn!("Actor gone: {}", public_key_id);
+                        return Ok(false);
                     } else {
                         return Err(e);
                     }
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 41c25f9..0729501 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -24,29 +24,28 @@ pub(crate) async fn route(
     client: web::Data<Requests>,
     jobs: web::Data<JobServer>,
     input: web::Json<AcceptedActivities>,
-    verified: Option<(SignatureVerified, DigestVerified)>,
+    digest_verified: Option<DigestVerified>,
+    signature_verified: Option<SignatureVerified>,
 ) -> Result<HttpResponse, Error> {
     let input = input.into_inner();
-    println!("ActivityActor: {:?}", input);
 
-    let actor = match actors
+    let kind = input.kind().ok_or(ErrorKind::MissingKind)?;
+
+    if digest_verified.is_some() && signature_verified.is_none() && *kind == ValidTypes::Delete {
+        return Ok(accepted(serde_json::json!({})));
+    } else if config.validate_signatures()
+        && (digest_verified.is_none() || signature_verified.is_none())
+    {
+        return Err(ErrorKind::NoSignature(None).into());
+    }
+
+    let actor = actors
         .get(
             input.actor()?.as_single_id().ok_or(ErrorKind::MissingId)?,
             &client,
         )
-        .await
-    {
-        Ok(actor) => actor.into_inner(),
-        Err(e) => {
-            // Eat up the message if actor is 410 and message is delete
-            let kind = input.kind().ok_or(ErrorKind::MissingKind)?;
-            if e.is_gone() && *kind == ValidTypes::Delete {
-                return Ok(accepted(serde_json::json!({})));
-            } else {
-                return Err(e);
-            }
-        }
-    };
+        .await?
+        .into_inner();
 
     let is_allowed = state.db.is_allowed(actor.id.clone()).await?;
     let is_connected = state.db.is_connected(actor.id.clone()).await?;
@@ -59,10 +58,8 @@ pub(crate) async fn route(
         return Err(ErrorKind::NotSubscribed(actor.id.to_string()).into());
     }
 
-    if config.validate_signatures() && verified.is_none() {
-        return Err(ErrorKind::NoSignature(actor.public_key_id.to_string()).into());
-    } else if config.validate_signatures() {
-        if let Some((verified, _)) = verified {
+    if config.validate_signatures() {
+        if let Some(verified) = signature_verified {
             if actor.public_key_id.as_str() != verified.key_id() {
                 tracing::error!("Actor signed with wrong key");
                 return Err(ErrorKind::BadActor(
@@ -71,10 +68,13 @@ pub(crate) async fn route(
                 )
                 .into());
             }
+        } else {
+            tracing::error!("This case should never be reachable, since I handle signature checks earlier in the flow. If you see this in a log it means I did it wrong");
+            return Err(ErrorKind::NoSignature(Some(actor.public_key_id.to_string())).into());
         }
     }
 
-    match input.kind().ok_or(ErrorKind::MissingKind)? {
+    match kind {
         ValidTypes::Accept => handle_accept(&config, input).await?,
         ValidTypes::Reject => handle_reject(&config, &jobs, input, actor).await?,
         ValidTypes::Announce | ValidTypes::Create => {

From cf7a25f935af3893d32fa91314b860f9ddd6da5e Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 11:44:50 -0600
Subject: [PATCH 25/87] Consider NoSignature a BadRequest

---
 src/error.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/error.rs b/src/error.rs
index ece3c06..dde9ba3 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -197,7 +197,7 @@ impl ResponseError for Error {
             ErrorKind::Kind(_)
             | ErrorKind::MissingKind
             | ErrorKind::MissingId
-            | ErrorKind::ObjectCount => StatusCode::BAD_REQUEST,
+            | ErrorKind::ObjectCount | ErrorKind::NoSignature(_) => StatusCode::BAD_REQUEST,
             _ => StatusCode::INTERNAL_SERVER_ERROR,
         }
     }

From fbcbf141dd0746544a7807dca72371981495965f Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 11:46:49 -0600
Subject: [PATCH 26/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1d0816d..d5ad1b2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.71"
+version = "0.3.72"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index a3c3272..425834f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.71"
+version = "0.3.72"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 815c18b899fd003291abdd9131ec86b87b452239 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 12:17:08 -0600
Subject: [PATCH 27/87] Update version number in various places

---
 README.md                      | 2 +-
 docker/prod/docker-compose.yml | 5 +++--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/README.md b/README.md
index ff02880..e0fced2 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ $ sudo docker run --rm -it \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \
-    asonix/relay:0.3.52
+    asonix/relay:0.3.72
 ```
 This will launch the relay with the database stored in "./sled/db-0.34" and listening on port 8080
 #### Cargo
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 7201789..7236765 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.3'
 
 services:
   relay:
-    image: asonix/relay:v0.3.8
+    image: asonix/relay:v0.3.72
     ports:
       - "8079:8079"
     restart: always
@@ -14,6 +14,7 @@ services:
       - RESTRICTED_MODE=false
       - VALIDATE_SIGNATURES=true
       - HTTPS=true
-      - DATABASE_URL=postgres://pg_user:pg_pass@pg_host:pg_port/pg_database
+      - SLED_PATH=/mnt/sled/db-0.34
       - PRETTY_LOG=false
       - PUBLISH_BLOCKS=true
+      - API_TOKEN=somepasswordishtoken

From 565a94d7560b49ec1b9321b4504ee905281fcdf4 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 12:23:06 -0600
Subject: [PATCH 28/87] clippy

---
 src/build.rs        | 2 +-
 src/routes/inbox.rs | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/build.rs b/src/build.rs
index 8db87a2..1c7e714 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -23,7 +23,7 @@ fn git_info() {
 fn version_info() -> Result<(), anyhow::Error> {
     let cargo_toml = Path::new(&std::env::var("CARGO_MANIFEST_DIR")?).join("Cargo.toml");
 
-    let mut file = File::open(&cargo_toml)?;
+    let mut file = File::open(cargo_toml)?;
 
     let mut cargo_data = String::new();
     file.read_to_string(&mut cargo_data)?;
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 0729501..991084b 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -17,6 +17,7 @@ use actix_web::{web, HttpResponse};
 use http_signature_normalization_actix::prelude::{DigestVerified, SignatureVerified};
 
 #[tracing::instrument(name = "Inbox", skip_all)]
+#[allow(clippy::too_many_arguments)]
 pub(crate) async fn route(
     state: web::Data<State>,
     actors: web::Data<ActorCache>,

From 359ec68aa0ae73a98dbf6e12f73e17cb6a2ea7a7 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 15:52:47 -0600
Subject: [PATCH 29/87] Add example systemd configuration

---
 systemd/example-relay.service     | 15 +++++++++++++++
 systemd/example-relay.service.env | 19 +++++++++++++++++++
 systemd/example-relay.socket      | 11 +++++++++++
 3 files changed, 45 insertions(+)
 create mode 100644 systemd/example-relay.service
 create mode 100644 systemd/example-relay.service.env
 create mode 100644 systemd/example-relay.socket

diff --git a/systemd/example-relay.service b/systemd/example-relay.service
new file mode 100644
index 0000000..3e6f7ed
--- /dev/null
+++ b/systemd/example-relay.service
@@ -0,0 +1,15 @@
+[Unit]
+Description=Activitypub Relay
+Documentation=https://git.asonix.dog/asonix/relay
+Wants=network.target
+After=network.target
+
+[Install]
+WantedBy=multi-user.target
+
+[Service]
+Type=simple
+EnvironmentFile=/etc/systemd/system/example-relay.service.env
+ExecStart=/path/to/relay
+Restart=always
+
diff --git a/systemd/example-relay.service.env b/systemd/example-relay.service.env
new file mode 100644
index 0000000..e74a6a0
--- /dev/null
+++ b/systemd/example-relay.service.env
@@ -0,0 +1,19 @@
+HOSTNAME='relay.example.com'
+ADDR='0.0.0.0'
+PORT='8080'
+RESTRICTED_MODE='true'
+VALIDATE_SIGNATURES='true'
+HTTPS='true'
+PRETTY_LOG='false'
+PUBLISH_BLOCKS='true'
+DEBUG='false'
+SLED_PATH='/opt/sled'
+TELEGRAM_ADMIN_HANDLE='myhandle'
+RUST_BACKTRACE='full'
+FOOTER_BLURB='Contact <a href="https://masto.example.com/@example">@example</a> for inquiries.'
+LOCAL_DOMAINS='masto.example.com'
+LOCAL_BLURB='<p>An ActivityPub relay for servers. Currently running somewhere. Let me know if you want to join!</p>'
+OPENTELEMETRY_URL='http://otel.example.com:4317'
+API_TOKEN='blahblahblahblahblahblahblah'
+TELEGRAM_TOKEN='blahblahblahblahblahblahblah'
+
diff --git a/systemd/example-relay.socket b/systemd/example-relay.socket
new file mode 100644
index 0000000..9c6ea0b
--- /dev/null
+++ b/systemd/example-relay.socket
@@ -0,0 +1,11 @@
+[Unit]
+Description=Activitypub Relay Socket
+Before=multi-user.target
+After=network.target
+
+[Socket]
+Service=example-relay.service
+ListenStream=8080
+
+[Install]
+WantedBy=sockets.target

From 675fddcfeb81fe7f4452610ec66497a6bfa9d359 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 16:08:39 -0600
Subject: [PATCH 30/87] Support Remove activity, forward verbatim

---
 src/apub.rs         | 3 ++-
 src/error.rs        | 3 ++-
 src/routes/inbox.rs | 2 +-
 3 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/src/apub.rs b/src/apub.rs
index 48f64d4..a99cacc 100644
--- a/src/apub.rs
+++ b/src/apub.rs
@@ -33,13 +33,14 @@ pub struct PublicKey {
 #[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, serde::Deserialize, serde::Serialize)]
 #[serde(rename_all = "PascalCase")]
 pub enum ValidTypes {
-    Add,
     Accept,
+    Add,
     Announce,
     Create,
     Delete,
     Follow,
     Reject,
+    Remove,
     Undo,
     Update,
 }
diff --git a/src/error.rs b/src/error.rs
index dde9ba3..2f9e658 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -197,7 +197,8 @@ impl ResponseError for Error {
             ErrorKind::Kind(_)
             | ErrorKind::MissingKind
             | ErrorKind::MissingId
-            | ErrorKind::ObjectCount | ErrorKind::NoSignature(_) => StatusCode::BAD_REQUEST,
+            | ErrorKind::ObjectCount
+            | ErrorKind::NoSignature(_) => StatusCode::BAD_REQUEST,
             _ => StatusCode::INTERNAL_SERVER_ERROR,
         }
     }
diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 991084b..18ff8da 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -82,7 +82,7 @@ pub(crate) async fn route(
             handle_announce(&state, &jobs, input, actor).await?
         }
         ValidTypes::Follow => handle_follow(&config, &jobs, input, actor).await?,
-        ValidTypes::Add | ValidTypes::Delete | ValidTypes::Update => {
+        ValidTypes::Add | ValidTypes::Delete | ValidTypes::Remove | ValidTypes::Update => {
             handle_forward(&jobs, input, actor).await?
         }
         ValidTypes::Undo => handle_undo(&config, &jobs, input, actor, is_connected).await?,

From 163e480076705f9d8ad1ada0354285be995ebbdd Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 16:30:48 -0600
Subject: [PATCH 31/87] Update deps

---
 Cargo.lock | 8 ++++----
 Cargo.toml | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index d5ad1b2..a817ff2 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4,9 +4,9 @@ version = 3
 
 [[package]]
 name = "activitystreams"
-version = "0.7.0-alpha.22"
+version = "0.7.0-alpha.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "713061473d42baa5527b1dbf07b86a506c48df3190a4fb840fb7fcea8cf1b724"
+checksum = "1e673a517c3cd11c3b1870be31f2c95580e30f9ca79e89082ba94325097ed9c4"
 dependencies = [
  "activitystreams-kinds",
  "iri-string",
@@ -3418,9 +3418,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.6.2"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d725b8fa6ef307b3f4856913523337de45c47cc79271bafd7acfb39559e3a2da"
+checksum = "7488d9441c630ea4cbde433aaccf00749ff306ffe1fda1cf13dfb06c85aceecd"
 dependencies = [
  "actix-web",
  "pin-project",
diff --git a/Cargo.toml b/Cargo.toml
index 425834f..7f2e8fc 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -91,7 +91,7 @@ default-features = false
 features = ["client", "server", "sha-2"]
 
 [dependencies.tracing-actix-web]
-version = "0.6.1"
+version = "0.7.0"
 
 [build-dependencies]
 anyhow = "1.0"

From 62a886d0bf2aeb8c68ad8b1ad79034d37413bea4 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 16:31:51 -0600
Subject: [PATCH 32/87] Bump version

---
 Cargo.lock                     | 2 +-
 Cargo.toml                     | 2 +-
 README.md                      | 2 +-
 docker/prod/docker-compose.yml | 2 +-
 4 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index a817ff2..7d999d7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.72"
+version = "0.3.73"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 7f2e8fc..5da8ced 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.72"
+version = "0.3.73"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"
diff --git a/README.md b/README.md
index e0fced2..af7b4b3 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ $ sudo docker run --rm -it \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \
-    asonix/relay:0.3.72
+    asonix/relay:0.3.73
 ```
 This will launch the relay with the database stored in "./sled/db-0.34" and listening on port 8080
 #### Cargo
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 7236765..7fe2704 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.3'
 
 services:
   relay:
-    image: asonix/relay:v0.3.72
+    image: asonix/relay:v0.3.73
     ports:
       - "8079:8079"
     restart: always

From efcec29d7bb195d1522a18f291559dbf39bd4863 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 16:32:16 -0600
Subject: [PATCH 33/87] Remove unused docker-related files

---
 docker/prod/Dockerfile     | 41 ------------------
 docker/prod/build-image.sh | 37 ----------------
 docker/prod/deploy.sh      | 87 --------------------------------------
 docker/prod/manifest.sh    | 43 -------------------
 4 files changed, 208 deletions(-)
 delete mode 100644 docker/prod/Dockerfile
 delete mode 100755 docker/prod/build-image.sh
 delete mode 100755 docker/prod/deploy.sh
 delete mode 100755 docker/prod/manifest.sh

diff --git a/docker/prod/Dockerfile b/docker/prod/Dockerfile
deleted file mode 100644
index 280aa95..0000000
--- a/docker/prod/Dockerfile
+++ /dev/null
@@ -1,41 +0,0 @@
-ARG REPO_ARCH=amd64
-
-# cross-build environment
-FROM asonix/rust-builder:$REPO_ARCH-latest AS builder
-
-ARG TAG=main
-ARG BINARY=relay
-ARG PROJECT=relay
-ARG GIT_REPOSITORY=https://git.asonix.dog/asonix/$PROJECT
-
-ENV \
- BINARY=${BINARY}
-
-ADD \
- --chown=build:build \
- $GIT_REPOSITORY/archive/$TAG.tar.gz \
- /opt/build/repo.tar.gz
-
-RUN \
- tar zxf repo.tar.gz
-
-WORKDIR /opt/build/$PROJECT
-
-RUN \
- build
-
-# production environment
-FROM asonix/rust-runner:$REPO_ARCH-latest
-
-ARG BINARY=relay
-
-ENV \
- BINARY=${BINARY}
-
-COPY \
- --from=builder \
- /opt/build/binary \
- /usr/bin/${BINARY}
-
-ENTRYPOINT ["/sbin/tini", "--"]
-CMD /usr/bin/${BINARY}
diff --git a/docker/prod/build-image.sh b/docker/prod/build-image.sh
deleted file mode 100755
index 2782f1e..0000000
--- a/docker/prod/build-image.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/usr/bin/env bash
-
-function require() {
-    if [ "$1" = "" ]; then
-        echo "input '$2' required"
-        print_help
-        exit 1
-    fi
-}
-
-function print_help() {
-    echo "deploy.sh"
-    echo ""
-    echo "Usage:"
-    echo "	deploy.sh [repo] [tag] [arch]"
-    echo ""
-    echo "Args:"
-    echo "	repo: The docker repository to publish the image"
-    echo "	tag: The tag applied to the docker image"
-    echo "	arch: The architecuture of the doker image"
-}
-
-REPO=$1
-TAG=$2
-ARCH=$3
-
-require "$REPO" repo
-require "$TAG" tag
-require "$ARCH" arch
-
-sudo docker build \
-    --pull \
-    --build-arg TAG=$TAG \
-    --build-arg REPO_ARCH=$ARCH \
-    -t $REPO:$ARCH-$TAG \
-    -f Dockerfile \
-    .
diff --git a/docker/prod/deploy.sh b/docker/prod/deploy.sh
deleted file mode 100755
index fcd7539..0000000
--- a/docker/prod/deploy.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/usr/bin/env bash
-
-function require() {
-    if [ "$1" = "" ]; then
-        echo "input '$2' required"
-        print_help
-        exit 1
-    fi
-}
-
-function print_help() {
-    echo "deploy.sh"
-    echo ""
-    echo "Usage:"
-    echo "	deploy.sh [tag] [branch] [push]"
-    echo ""
-    echo "Args:"
-    echo "	tag: The git tag to be applied to the repository and docker build"
-    echo "	branch: The git branch to use for tagging and publishing"
-    echo "	push: Whether or not to push the image"
-    echo ""
-    echo "Examples:"
-    echo "	./deploy.sh v0.3.0-alpha.13 main true"
-    echo "	./deploy.sh v0.3.0-alpha.13-shell-out asonix/shell-out false"
-}
-
-function build_image() {
-    tag=$1
-    arch=$2
-    push=$3
-
-    ./build-image.sh asonix/relay $tag $arch
-
-    sudo docker tag asonix/relay:$arch-$tag asonix/relay:$arch-latest
-
-    if [ "$push" == "true" ]; then
-        sudo docker push asonix/relay:$arch-$tag
-        sudo docker push asonix/relay:$arch-latest
-    fi
-}
-
-# Creating the new tag
-new_tag="$1"
-branch="$2"
-push=$3
-
-require "$new_tag" "tag"
-require "$branch" "branch"
-require "$push" "push"
-
-if ! sudo docker run --rm -it arm64v8/alpine:3.11 /bin/sh -c 'echo "docker is configured correctly"'
-then
-    echo "docker is not configured to run on qemu-emulated architectures, fixing will require sudo"
-    sudo docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
-fi
-
-set -xe
-
-git checkout $branch
-
-# Changing the docker-compose prod
-sed -i "s/asonix\/relay:.*/asonix\/relay:$new_tag/" docker-compose.yml
-git add ../prod/docker-compose.yml
-# The commit
-git commit -m"Version $new_tag"
-git tag $new_tag
-
-# Push
-git push origin $new_tag
-git push
-
-# Build for arm64v8, arm32v7 and amd64
-build_image $new_tag arm64v8 $push
-build_image $new_tag arm32v7 $push
-build_image $new_tag amd64 $push
-
-# Build for other archs
-# TODO
-
-if [ "$push" == "true" ]; then
-    ./manifest.sh relay $new_tag
-    ./manifest.sh relay latest
-
-    # pushd ../../
-    # cargo publish
-    # popd
-fi
diff --git a/docker/prod/manifest.sh b/docker/prod/manifest.sh
deleted file mode 100755
index d426a97..0000000
--- a/docker/prod/manifest.sh
+++ /dev/null
@@ -1,43 +0,0 @@
-#!/usr/bin/env bash
-
-function require() {
-    if [ "$1" = "" ]; then
-        echo "input '$2' required"
-        print_help
-        exit 1
-    fi
-}
-function print_help() {
-    echo "deploy.sh"
-    echo ""
-    echo "Usage:"
-    echo "	manifest.sh [repo] [tag]"
-    echo ""
-    echo "Args:"
-    echo "	repo: The docker repository to update"
-    echo "	tag: The git tag to be applied to the image manifest"
-}
-
-REPO=$1
-TAG=$2
-
-require "$REPO" "repo"
-require "$TAG" "tag"
-
-set -xe
-
-sudo docker manifest create asonix/$REPO:$TAG \
-    -a asonix/$REPO:arm64v8-$TAG \
-    -a asonix/$REPO:arm32v7-$TAG \
-    -a asonix/$REPO:amd64-$TAG
-
-sudo docker manifest annotate asonix/$REPO:$TAG \
-    asonix/$REPO:arm64v8-$TAG --os linux --arch arm64 --variant v8
-
-sudo docker manifest annotate asonix/$REPO:$TAG \
-    asonix/$REPO:arm32v7-$TAG --os linux --arch arm --variant v7
-
-sudo docker manifest annotate asonix/$REPO:$TAG \
-    asonix/$REPO:amd64-$TAG --os linux --arch amd64
-
-sudo docker manifest push asonix/$REPO:$TAG --purge

From 40eb12258dc359f134a423133d923b49006899ef Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 21:05:53 -0600
Subject: [PATCH 34/87] Record id in inbox route

---
 src/routes/inbox.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 18ff8da..202f803 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -16,7 +16,7 @@ use activitystreams::{
 use actix_web::{web, HttpResponse};
 use http_signature_normalization_actix::prelude::{DigestVerified, SignatureVerified};
 
-#[tracing::instrument(name = "Inbox", skip_all)]
+#[tracing::instrument(name = "Inbox", skip_all, fields(id = input.id_unchecked().map(|id| id.as_str())))]
 #[allow(clippy::too_many_arguments)]
 pub(crate) async fn route(
     state: web::Data<State>,

From 689d85befb385a5e848664772ec79651ee6be875 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 21:07:25 -0600
Subject: [PATCH 35/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 7d999d7..5b05c26 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.73"
+version = "0.3.74"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 5da8ced..4b02e8a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.73"
+version = "0.3.74"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 4e5fabce5f3b939ba0bdd1ce3f3a59c690e99776 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 21:45:52 -0600
Subject: [PATCH 36/87] Also debug Kind in inbox

---
 src/routes/inbox.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 202f803..18e4949 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -16,7 +16,7 @@ use activitystreams::{
 use actix_web::{web, HttpResponse};
 use http_signature_normalization_actix::prelude::{DigestVerified, SignatureVerified};
 
-#[tracing::instrument(name = "Inbox", skip_all, fields(id = input.id_unchecked().map(|id| id.as_str())))]
+#[tracing::instrument(name = "Inbox", skip_all, fields(id = tracing::field::debug(&input.id_unchecked()), kind = tracing::field::debug(&input.kind())))]
 #[allow(clippy::too_many_arguments)]
 pub(crate) async fn route(
     state: web::Data<State>,

From 37b2afe3448b76dc46d7f5755d55cb4fca2f47b6 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 21:46:27 -0600
Subject: [PATCH 37/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5b05c26..9acf19b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.74"
+version = "0.3.75"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 4b02e8a..043bb71 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.74"
+version = "0.3.75"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 943f679a6927177d0d92fcec96c3bd8e526de50e Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 22:24:58 -0600
Subject: [PATCH 38/87] Allow activities without IDs, fetch actor unchecked

---
 src/routes/inbox.rs | 47 +++++++++++++++++++++++----------------------
 1 file changed, 24 insertions(+), 23 deletions(-)

diff --git a/src/routes/inbox.rs b/src/routes/inbox.rs
index 18e4949..133d7dd 100644
--- a/src/routes/inbox.rs
+++ b/src/routes/inbox.rs
@@ -40,13 +40,30 @@ pub(crate) async fn route(
         return Err(ErrorKind::NoSignature(None).into());
     }
 
-    let actor = actors
-        .get(
-            input.actor()?.as_single_id().ok_or(ErrorKind::MissingId)?,
-            &client,
-        )
-        .await?
-        .into_inner();
+    let actor_id = if input.id_unchecked().is_some() {
+        input.actor()?.as_single_id().ok_or(ErrorKind::MissingId)?
+    } else {
+        input
+            .actor_unchecked()
+            .as_single_id()
+            .ok_or(ErrorKind::MissingId)?
+    };
+
+    let actor = actors.get(actor_id, &client).await?.into_inner();
+
+    if let Some(verified) = signature_verified {
+        if actor.public_key_id.as_str() != verified.key_id() {
+            tracing::error!("Actor signed with wrong key");
+            return Err(ErrorKind::BadActor(
+                actor.public_key_id.to_string(),
+                verified.key_id().to_owned(),
+            )
+            .into());
+        }
+    } else if config.validate_signatures() {
+        tracing::error!("This case should never be reachable, since I handle signature checks earlier in the flow. If you see this in a log it means I did it wrong");
+        return Err(ErrorKind::NoSignature(Some(actor.public_key_id.to_string())).into());
+    }
 
     let is_allowed = state.db.is_allowed(actor.id.clone()).await?;
     let is_connected = state.db.is_connected(actor.id.clone()).await?;
@@ -59,22 +76,6 @@ pub(crate) async fn route(
         return Err(ErrorKind::NotSubscribed(actor.id.to_string()).into());
     }
 
-    if config.validate_signatures() {
-        if let Some(verified) = signature_verified {
-            if actor.public_key_id.as_str() != verified.key_id() {
-                tracing::error!("Actor signed with wrong key");
-                return Err(ErrorKind::BadActor(
-                    actor.public_key_id.to_string(),
-                    verified.key_id().to_owned(),
-                )
-                .into());
-            }
-        } else {
-            tracing::error!("This case should never be reachable, since I handle signature checks earlier in the flow. If you see this in a log it means I did it wrong");
-            return Err(ErrorKind::NoSignature(Some(actor.public_key_id.to_string())).into());
-        }
-    }
-
     match kind {
         ValidTypes::Accept => handle_accept(&config, input).await?,
         ValidTypes::Reject => handle_reject(&config, &jobs, input, actor).await?,

From b49eeaf8227d307bd509c945a68ead6d7376bcc6 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 19 Dec 2022 22:25:27 -0600
Subject: [PATCH 39/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 9acf19b..ed762ec 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.75"
+version = "0.3.76"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 043bb71..73346c9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.75"
+version = "0.3.76"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 88b03830846c521c0a40efb1d2e5ab9dd5e14f40 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Wed, 21 Dec 2022 16:51:17 -0600
Subject: [PATCH 40/87] Keep track of when servers were last seen

---
 Cargo.lock                     |  1 +
 Cargo.toml                     |  1 +
 src/admin.rs                   |  8 +++++
 src/admin/client.rs            |  6 +++-
 src/admin/routes.rs            | 21 ++++++++++++-
 src/args.rs                    | 17 ++++++++++-
 src/config.rs                  | 40 ++++++++++---------------
 src/data.rs                    |  2 ++
 src/data/last_online.rs        | 28 +++++++++++++++++
 src/data/state.rs              |  5 ++++
 src/db.rs                      | 55 ++++++++++++++++++++++++++++++++--
 src/jobs.rs                    |  5 +++-
 src/jobs/record_last_online.rs | 28 +++++++++++++++++
 src/main.rs                    | 36 +++++++++++++++++++++-
 src/requests.rs                |  9 +++++-
 15 files changed, 228 insertions(+), 34 deletions(-)
 create mode 100644 src/data/last_online.rs
 create mode 100644 src/jobs/record_last_online.rs

diff --git a/Cargo.lock b/Cargo.lock
index ed762ec..8aa2297 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -340,6 +340,7 @@ dependencies = [
  "sled",
  "teloxide",
  "thiserror",
+ "time",
  "tokio",
  "toml",
  "tracing",
diff --git a/Cargo.toml b/Cargo.toml
index 73346c9..4422028 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -66,6 +66,7 @@ teloxide = { version = "0.11.1", default-features = false, features = [
   "rustls",
 ] }
 thiserror = "1.0"
+time = { version = "0.3.17", features = ["serde"] }
 tracing = "0.1"
 tracing-awc = "0.1.6"
 tracing-error = "0.2"
diff --git a/src/admin.rs b/src/admin.rs
index e7fc665..156a5d9 100644
--- a/src/admin.rs
+++ b/src/admin.rs
@@ -1,4 +1,6 @@
 use activitystreams::iri_string::types::IriString;
+use std::collections::{BTreeMap, BTreeSet};
+use time::OffsetDateTime;
 
 pub mod client;
 pub mod routes;
@@ -22,3 +24,9 @@ pub(crate) struct BlockedDomains {
 pub(crate) struct ConnectedActors {
     pub(crate) connected_actors: Vec<IriString>,
 }
+
+#[derive(serde::Deserialize, serde::Serialize)]
+pub(crate) struct LastSeen {
+    pub(crate) last_seen: BTreeMap<OffsetDateTime, BTreeSet<String>>,
+    pub(crate) never: Vec<String>,
+}
diff --git a/src/admin/client.rs b/src/admin/client.rs
index 3602487..fdb1687 100644
--- a/src/admin/client.rs
+++ b/src/admin/client.rs
@@ -1,5 +1,5 @@
 use crate::{
-    admin::{AllowedDomains, BlockedDomains, ConnectedActors, Domains},
+    admin::{AllowedDomains, BlockedDomains, ConnectedActors, Domains, LastSeen},
     collector::Snapshot,
     config::{AdminUrlKind, Config},
     error::{Error, ErrorKind},
@@ -55,6 +55,10 @@ pub(crate) async fn stats(client: &Client, config: &Config) -> Result<Snapshot,
     get_results(client, config, AdminUrlKind::Stats).await
 }
 
+pub(crate) async fn last_seen(client: &Client, config: &Config) -> Result<LastSeen, Error> {
+    get_results(client, config, AdminUrlKind::LastSeen).await
+}
+
 async fn get_results<T: DeserializeOwned>(
     client: &Client,
     config: &Config,
diff --git a/src/admin/routes.rs b/src/admin/routes.rs
index 6578bfd..c13a6e3 100644
--- a/src/admin/routes.rs
+++ b/src/admin/routes.rs
@@ -1,5 +1,5 @@
 use crate::{
-    admin::{AllowedDomains, BlockedDomains, ConnectedActors, Domains},
+    admin::{AllowedDomains, BlockedDomains, ConnectedActors, Domains, LastSeen},
     collector::{MemoryCollector, Snapshot},
     error::Error,
     extractors::Admin,
@@ -8,6 +8,8 @@ use actix_web::{
     web::{Data, Json},
     HttpResponse,
 };
+use std::collections::{BTreeMap, BTreeSet};
+use time::OffsetDateTime;
 
 pub(crate) async fn allow(
     admin: Admin,
@@ -69,3 +71,20 @@ pub(crate) async fn stats(
 ) -> Result<Json<Snapshot>, Error> {
     Ok(Json(collector.snapshot()))
 }
+
+pub(crate) async fn last_seen(admin: Admin) -> Result<Json<LastSeen>, Error> {
+    let nodes = admin.db_ref().last_seen().await?;
+
+    let mut last_seen: BTreeMap<OffsetDateTime, BTreeSet<String>> = BTreeMap::new();
+    let mut never = Vec::new();
+
+    for (domain, datetime) in nodes {
+        if let Some(datetime) = datetime {
+            last_seen.entry(datetime).or_default().insert(domain);
+        } else {
+            never.push(domain);
+        }
+    }
+
+    Ok(Json(LastSeen { last_seen, never }))
+}
diff --git a/src/args.rs b/src/args.rs
index 18a4059..155b296 100644
--- a/src/args.rs
+++ b/src/args.rs
@@ -17,11 +17,22 @@ pub(crate) struct Args {
 
     #[arg(short, long, help = "Get statistics from the server")]
     stats: bool,
+
+    #[arg(
+        short,
+        long,
+        help = "List domains by when they were last succesfully contacted"
+    )]
+    contacted: bool,
 }
 
 impl Args {
     pub(crate) fn any(&self) -> bool {
-        !self.blocks.is_empty() || !self.allowed.is_empty() || self.list || self.stats
+        !self.blocks.is_empty()
+            || !self.allowed.is_empty()
+            || self.list
+            || self.stats
+            || self.contacted
     }
 
     pub(crate) fn new() -> Self {
@@ -47,4 +58,8 @@ impl Args {
     pub(crate) fn stats(&self) -> bool {
         self.stats
     }
+
+    pub(crate) fn contacted(&self) -> bool {
+        self.contacted
+    }
 }
diff --git a/src/config.rs b/src/config.rs
index 3a46833..bd70162 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -92,6 +92,7 @@ pub enum AdminUrlKind {
     Blocked,
     Connected,
     Stats,
+    LastSeen,
 }
 
 impl std::fmt::Debug for Config {
@@ -429,33 +430,22 @@ impl Config {
     }
 
     fn do_generate_admin_url(&self, kind: AdminUrlKind) -> Result<IriString, Error> {
-        let iri = match kind {
-            AdminUrlKind::Allow => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/allow")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Disallow => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/disallow")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Block => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/block")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Unblock => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/unblock")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Allowed => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/allowed")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Blocked => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/blocked")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Connected => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/connected")?.as_ref())
-                .try_to_dedicated_string()?,
-            AdminUrlKind::Stats => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new("api/v1/admin/stats")?.as_ref())
-                .try_to_dedicated_string()?,
+        let path = match kind {
+            AdminUrlKind::Allow => "api/v1/admin/allow",
+            AdminUrlKind::Disallow => "api/v1/admin/disallow",
+            AdminUrlKind::Block => "api/v1/admin/block",
+            AdminUrlKind::Unblock => "api/v1/admin/unblock",
+            AdminUrlKind::Allowed => "api/v1/admin/allowed",
+            AdminUrlKind::Blocked => "api/v1/admin/blocked",
+            AdminUrlKind::Connected => "api/v1/admin/connected",
+            AdminUrlKind::Stats => "api/v1/admin/stats",
+            AdminUrlKind::LastSeen => "api/v1/admin/last_seen",
         };
 
+        let iri = FixedBaseResolver::new(self.base_uri.as_ref())
+            .resolve(IriRelativeStr::new(path)?.as_ref())
+            .try_to_dedicated_string()?;
+
         Ok(iri)
     }
 }
diff --git a/src/data.rs b/src/data.rs
index 918bdf7..1125149 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -1,9 +1,11 @@
 mod actor;
+mod last_online;
 mod media;
 mod node;
 mod state;
 
 pub(crate) use actor::ActorCache;
+pub(crate) use last_online::LastOnline;
 pub(crate) use media::MediaCache;
 pub(crate) use node::{Node, NodeCache};
 pub(crate) use state::State;
diff --git a/src/data/last_online.rs b/src/data/last_online.rs
new file mode 100644
index 0000000..889d804
--- /dev/null
+++ b/src/data/last_online.rs
@@ -0,0 +1,28 @@
+use activitystreams::iri_string::types::IriStr;
+use std::{collections::HashMap, sync::Mutex};
+use time::OffsetDateTime;
+
+pub(crate) struct LastOnline {
+    domains: Mutex<HashMap<String, OffsetDateTime>>,
+}
+
+impl LastOnline {
+    pub(crate) fn mark_seen(&self, iri: &IriStr) {
+        if let Some(authority) = iri.authority_str() {
+            self.domains
+                .lock()
+                .unwrap()
+                .insert(authority.to_string(), OffsetDateTime::now_utc());
+        }
+    }
+
+    pub(crate) fn take(&self) -> HashMap<String, OffsetDateTime> {
+        std::mem::take(&mut *self.domains.lock().unwrap())
+    }
+
+    pub(crate) fn empty() -> Self {
+        Self {
+            domains: Mutex::new(HashMap::default()),
+        }
+    }
+}
diff --git a/src/data/state.rs b/src/data/state.rs
index 31f0811..4387974 100644
--- a/src/data/state.rs
+++ b/src/data/state.rs
@@ -12,6 +12,8 @@ use rand::thread_rng;
 use rsa::{RsaPrivateKey, RsaPublicKey};
 use std::sync::{Arc, RwLock};
 
+use super::LastOnline;
+
 #[derive(Clone)]
 pub struct State {
     pub(crate) public_key: RsaPublicKey,
@@ -19,6 +21,7 @@ pub struct State {
     object_cache: Arc<RwLock<LruCache<IriString, IriString>>>,
     node_cache: NodeCache,
     breakers: Breakers,
+    pub(crate) last_online: Arc<LastOnline>,
     pub(crate) db: Db,
 }
 
@@ -43,6 +46,7 @@ impl State {
             self.private_key.clone(),
             config.user_agent(),
             self.breakers.clone(),
+            self.last_online.clone(),
         )
     }
 
@@ -114,6 +118,7 @@ impl State {
             node_cache: NodeCache::new(db.clone()),
             breakers: Breakers::default(),
             db,
+            last_online: Arc::new(LastOnline::empty()),
         };
 
         Ok(state)
diff --git a/src/db.rs b/src/db.rs
index 685405f..6d3064f 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -7,8 +7,13 @@ use rsa::{
     pkcs8::{DecodePrivateKey, EncodePrivateKey},
     RsaPrivateKey,
 };
-use sled::Tree;
-use std::{collections::HashMap, sync::Arc, time::SystemTime};
+use sled::{Batch, Tree};
+use std::{
+    collections::{BTreeMap, HashMap},
+    sync::Arc,
+    time::SystemTime,
+};
+use time::OffsetDateTime;
 use uuid::Uuid;
 
 #[derive(Clone, Debug)]
@@ -28,6 +33,7 @@ struct Inner {
     actor_id_info: Tree,
     actor_id_instance: Tree,
     actor_id_contact: Tree,
+    last_seen: Tree,
     restricted_mode: bool,
 }
 
@@ -247,6 +253,7 @@ impl Db {
                 actor_id_info: db.open_tree("actor-id-info")?,
                 actor_id_instance: db.open_tree("actor-id-instance")?,
                 actor_id_contact: db.open_tree("actor-id-contact")?,
+                last_seen: db.open_tree("last-seen")?,
                 restricted_mode,
             }),
         })
@@ -254,7 +261,7 @@ impl Db {
 
     async fn unblock<T>(
         &self,
-        f: impl Fn(&Inner) -> Result<T, Error> + Send + 'static,
+        f: impl FnOnce(&Inner) -> Result<T, Error> + Send + 'static,
     ) -> Result<T, Error>
     where
         T: Send + 'static,
@@ -266,6 +273,48 @@ impl Db {
         Ok(t)
     }
 
+    pub(crate) async fn mark_last_seen(
+        &self,
+        nodes: HashMap<String, OffsetDateTime>,
+    ) -> Result<(), Error> {
+        let mut batch = Batch::default();
+
+        for (domain, datetime) in nodes {
+            let datetime_string = serde_json::to_vec(&datetime)?;
+
+            batch.insert(domain.as_bytes(), datetime_string);
+        }
+
+        self.unblock(move |inner| inner.last_seen.apply_batch(batch).map_err(Error::from))
+            .await
+    }
+
+    pub(crate) async fn last_seen(
+        &self,
+    ) -> Result<BTreeMap<String, Option<OffsetDateTime>>, Error> {
+        self.unblock(|inner| {
+            let mut map = BTreeMap::new();
+
+            for iri in inner.connected() {
+                let Some(authority_str) = iri.authority_str() else {
+                    continue;
+                };
+
+                if let Some(datetime) = inner.last_seen.get(authority_str)? {
+                    map.insert(
+                        authority_str.to_string(),
+                        Some(serde_json::from_slice(&datetime)?),
+                    );
+                } else {
+                    map.insert(authority_str.to_string(), None);
+                }
+            }
+
+            Ok(map)
+        })
+        .await
+    }
+
     pub(crate) async fn connected_ids(&self) -> Result<Vec<IriString>, Error> {
         self.unblock(|inner| Ok(inner.connected().collect())).await
     }
diff --git a/src/jobs.rs b/src/jobs.rs
index 014bd72..0bad1ac 100644
--- a/src/jobs.rs
+++ b/src/jobs.rs
@@ -5,6 +5,7 @@ mod deliver_many;
 mod instance;
 mod nodeinfo;
 mod process_listeners;
+mod record_last_online;
 
 pub(crate) use self::{
     contact::QueryContact, deliver::Deliver, deliver_many::DeliverMany, instance::QueryInstance,
@@ -15,7 +16,7 @@ use crate::{
     config::Config,
     data::{ActorCache, MediaCache, NodeCache, State},
     error::{Error, ErrorKind},
-    jobs::process_listeners::Listeners,
+    jobs::{process_listeners::Listeners, record_last_online::RecordLastOnline},
     requests::Requests,
 };
 use background_jobs::{
@@ -62,6 +63,7 @@ pub(crate) fn create_workers(
     .register::<QueryInstance>()
     .register::<Listeners>()
     .register::<QueryContact>()
+    .register::<RecordLastOnline>()
     .register::<apub::Announce>()
     .register::<apub::Follow>()
     .register::<apub::Forward>()
@@ -73,6 +75,7 @@ pub(crate) fn create_workers(
     .start_with_threads(parallelism);
 
     shared.every(Duration::from_secs(60 * 5), Listeners);
+    shared.every(Duration::from_secs(60 * 10), RecordLastOnline);
 
     let job_server = JobServer::new(shared.queue_handle().clone());
 
diff --git a/src/jobs/record_last_online.rs b/src/jobs/record_last_online.rs
new file mode 100644
index 0000000..3c81b31
--- /dev/null
+++ b/src/jobs/record_last_online.rs
@@ -0,0 +1,28 @@
+use crate::{error::Error, jobs::JobState};
+use background_jobs::{ActixJob, Backoff};
+use std::{future::Future, pin::Pin};
+
+#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
+pub(crate) struct RecordLastOnline;
+
+impl RecordLastOnline {
+    #[tracing::instrument(skip(state))]
+    async fn perform(self, state: JobState) -> Result<(), Error> {
+        let nodes = state.state.last_online.take();
+
+        state.state.db.mark_last_seen(nodes).await
+    }
+}
+
+impl ActixJob for RecordLastOnline {
+    type State = JobState;
+    type Future = Pin<Box<dyn Future<Output = Result<(), anyhow::Error>>>>;
+
+    const NAME: &'static str = "relay::jobs::RecordLastOnline";
+    const QUEUE: &'static str = "maintenance";
+    const BACKOFF: Backoff = Backoff::Linear(1);
+
+    fn run(self, state: Self::State) -> Self::Future {
+        Box::pin(async move { self.perform(state).await.map_err(Into::into) })
+    }
+}
diff --git a/src/main.rs b/src/main.rs
index 5605a48..dccd8bb 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -144,6 +144,39 @@ async fn do_client_main(config: Config, args: Args) -> Result<(), anyhow::Error>
         println!("Updated lists");
     }
 
+    if args.contacted() {
+        let last_seen = admin::client::last_seen(&client, &config).await?;
+
+        let mut report = String::from("Contacted:");
+
+        if !last_seen.never.is_empty() {
+            report += "\nNever seen:\n";
+        }
+
+        for domain in last_seen.never {
+            report += "\t";
+            report += &domain;
+            report += "\n";
+        }
+
+        if !last_seen.last_seen.is_empty() {
+            report += "\nSeen:\n";
+        }
+
+        for (datetime, domains) in last_seen.last_seen {
+            for domain in domains {
+                report += "\t";
+                report += &datetime.to_string();
+                report += " - ";
+                report += &domain;
+                report += "\n";
+            }
+        }
+
+        report += "\n";
+        println!("{report}");
+    }
+
     if args.list() {
         let (blocked, allowed, connected) = tokio::try_join!(
             admin::client::blocked(&client, &config),
@@ -258,7 +291,8 @@ async fn do_server_main(
                         .route("/allowed", web::get().to(admin::routes::allowed))
                         .route("/blocked", web::get().to(admin::routes::blocked))
                         .route("/connected", web::get().to(admin::routes::connected))
-                        .route("/stats", web::get().to(admin::routes::stats)),
+                        .route("/stats", web::get().to(admin::routes::stats))
+                        .route("/last_seen", web::get().to(admin::routes::last_seen)),
                 ),
             )
     });
diff --git a/src/requests.rs b/src/requests.rs
index 332024a..9a1bc50 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -1,4 +1,7 @@
-use crate::error::{Error, ErrorKind};
+use crate::{
+    data::LastOnline,
+    error::{Error, ErrorKind},
+};
 use activitystreams::iri_string::types::IriString;
 use actix_web::http::header::Date;
 use awc::{error::SendRequestError, Client, ClientResponse};
@@ -146,6 +149,7 @@ pub(crate) struct Requests {
     private_key: RsaPrivateKey,
     config: Config,
     breakers: Breakers,
+    last_online: Arc<LastOnline>,
 }
 
 impl std::fmt::Debug for Requests {
@@ -174,6 +178,7 @@ impl Requests {
         private_key: RsaPrivateKey,
         user_agent: String,
         breakers: Breakers,
+        last_online: Arc<LastOnline>,
     ) -> Self {
         Requests {
             client: Rc::new(RefCell::new(build_client(&user_agent))),
@@ -184,6 +189,7 @@ impl Requests {
             private_key,
             config: Config::default().mastodon_compat(),
             breakers,
+            last_online,
         }
     }
 
@@ -233,6 +239,7 @@ impl Requests {
             return Err(ErrorKind::Status(parsed_url.to_string(), res.status()).into());
         }
 
+        self.last_online.mark_seen(&parsed_url);
         self.breakers.succeed(&parsed_url);
 
         Ok(res)

From 30dd16a8893fbbd6fe3f7a32078bc731f2de9ed7 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Wed, 21 Dec 2022 16:58:05 -0600
Subject: [PATCH 41/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 8aa2297..ec4a11f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.76"
+version = "0.3.77"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 4422028..c58370d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.76"
+version = "0.3.77"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 07b961c28f1686a061031ca5deb567e4eb9589ab Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Wed, 21 Dec 2022 16:59:19 -0600
Subject: [PATCH 42/87] Bump deps

---
 Cargo.lock | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index ec4a11f..cf4a6bd 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -696,9 +696,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.0.29"
+version = "4.0.30"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4d63b9e9c07271b9957ad22c173bae2a4d9a81127680962039296abcd2f8251d"
+checksum = "656ad1e55e23d287773f7d8192c300dc715c3eeded93b3da651d11c42cfd74d2"
 dependencies = [
  "bitflags",
  "clap_derive",
@@ -1263,15 +1263,6 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
 
-[[package]]
-name = "hermit-abi"
-version = "0.1.19"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
-
 [[package]]
 name = "hermit-abi"
 version = "0.2.6"
@@ -1492,11 +1483,11 @@ dependencies = [
 
 [[package]]
 name = "is-terminal"
-version = "0.4.1"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "927609f78c2913a6f6ac3c27a4fe87f43e2a35367c0c4b0f8265e8f49a104330"
+checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
 dependencies = [
- "hermit-abi 0.2.6",
+ "hermit-abi",
  "io-lifetimes",
  "rustix",
  "windows-sys",
@@ -1968,11 +1959,11 @@ dependencies = [
 
 [[package]]
 name = "num_cpus"
-version = "1.14.0"
+version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6058e64324c71e02bc2b150e4f3bc8286db6c83092132ffa3f6b1eab0f9def5"
+checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "hermit-abi 0.1.19",
+ "hermit-abi",
  "libc",
 ]
 
@@ -2388,9 +2379,9 @@ dependencies = [
 
 [[package]]
 name = "prost"
-version = "0.11.3"
+version = "0.11.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0b18e655c21ff5ac2084a5ad0611e827b3f92badf79f4910b5a5c58f4d87ff0"
+checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592"
 dependencies = [
  "bytes",
  "prost-derive",
@@ -2398,9 +2389,9 @@ dependencies = [
 
 [[package]]
 name = "prost-build"
-version = "0.11.4"
+version = "0.11.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "276470f7f281b0ed53d2ae42dd52b4a8d08853a3c70e7fe95882acbb98a6ae94"
+checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6"
 dependencies = [
  "bytes",
  "heck",
@@ -2420,9 +2411,9 @@ dependencies = [
 
 [[package]]
 name = "prost-derive"
-version = "0.11.2"
+version = "0.11.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "164ae68b6587001ca506d3bf7f1000bfa248d0e1217b618108fba4ec1d0cc306"
+checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
@@ -2433,9 +2424,9 @@ dependencies = [
 
 [[package]]
 name = "prost-types"
-version = "0.11.2"
+version = "0.11.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "747761bc3dc48f9a34553bf65605cf6cb6288ba219f3450b4275dbd81539551a"
+checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091"
 dependencies = [
  "bytes",
  "prost",

From fafba692582a08240305f574fd87e8e9279aa598 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 26 Dec 2022 10:56:42 -0600
Subject: [PATCH 43/87] Add optional prometheus scrape endpoint

---
 Cargo.lock              |  21 +-
 Cargo.toml              |   5 +-
 README.md               |   8 +-
 src/collector.rs        | 417 +---------------------------------------
 src/collector/double.rs | 133 +++++++++++++
 src/collector/stats.rs  | 414 +++++++++++++++++++++++++++++++++++++++
 src/config.rs           |  38 +++-
 src/main.rs             |  16 +-
 8 files changed, 633 insertions(+), 419 deletions(-)
 create mode 100644 src/collector/double.rs
 create mode 100644 src/collector/stats.rs

diff --git a/Cargo.lock b/Cargo.lock
index cf4a6bd..008efcf 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -298,7 +298,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.77"
+version = "0.3.78"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
@@ -320,6 +320,7 @@ dependencies = [
  "http-signature-normalization-actix",
  "lru",
  "metrics",
+ "metrics-exporter-prometheus",
  "metrics-util",
  "mime",
  "minify-html",
@@ -1717,6 +1718,24 @@ dependencies = [
  "portable-atomic",
 ]
 
+[[package]]
+name = "metrics-exporter-prometheus"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8603921e1f54ef386189335f288441af761e0fc61bcb552168d9cedfe63ebc70"
+dependencies = [
+ "hyper",
+ "indexmap",
+ "ipnet",
+ "metrics",
+ "metrics-util",
+ "parking_lot 0.12.1",
+ "portable-atomic",
+ "quanta",
+ "thiserror",
+ "tokio",
+]
+
 [[package]]
 name = "metrics-macros"
 version = "0.6.0"
diff --git a/Cargo.toml b/Cargo.toml
index c58370d..a8705cd 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.77"
+version = "0.3.78"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"
@@ -43,6 +43,9 @@ dotenv = "0.15.0"
 futures-util = "0.3.17"
 lru = "0.8.0"
 metrics = "0.20.1"
+metrics-exporter-prometheus = { version = "0.11.0", default-features = false, features = [
+  "http-listener",
+] }
 metrics-util = "0.14.0"
 mime = "0.3.16"
 minify-html = "0.10.0"
diff --git a/README.md b/README.md
index af7b4b3..dfa6356 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ $ sudo docker run --rm -it \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \
-    asonix/relay:0.3.73
+    asonix/relay:0.3.78
 ```
 This will launch the relay with the database stored in "./sled/db-0.34" and listening on port 8080
 #### Cargo
@@ -103,6 +103,8 @@ TLS_CERT=/path/to/cert
 FOOTER_BLURB="Contact <a href=\"https://masto.asonix.dog/@asonix\">@asonix</a> for inquiries"
 LOCAL_DOMAINS=masto.asonix.dog
 LOCAL_BLURB="<p>Welcome to my cool relay where I have cool relay things happening. I hope you enjoy your stay!</p>"
+PROMETHEUS_ADDR=0.0.0.0
+PROMETHEUS_PORT=9000
 ```
 
 #### Descriptions
@@ -146,6 +148,10 @@ Optional - Add custom notes in the footer of the page
 Optional - domains of mastodon servers run by the same admin as the relay
 ##### `LOCAL_BLURB`
 Optional - description for the relay
+##### `PROMETHEUS_ADDR`
+Optional - Address to bind to for serving the prometheus scrape endpoint
+##### `PROMETHEUS_PORT`
+Optional - Port to bind to for serving the prometheus scrape endpoint
 
 ### Subscribing
 Mastodon admins can subscribe to this relay by adding the `/inbox` route to their relay settings.
diff --git a/src/collector.rs b/src/collector.rs
index 0d3536d..b2758b0 100644
--- a/src/collector.rs
+++ b/src/collector.rs
@@ -1,414 +1,5 @@
-use metrics::{Key, Recorder, SetRecorderError};
-use metrics_util::{
-    registry::{AtomicStorage, GenerationalStorage, Recency, Registry},
-    MetricKindMask, Summary,
-};
-use quanta::Clock;
-use std::{
-    collections::{BTreeMap, HashMap},
-    sync::{atomic::Ordering, Arc, RwLock},
-    time::Duration,
-};
+mod double;
+mod stats;
 
-const SECONDS: u64 = 1;
-const MINUTES: u64 = 60 * SECONDS;
-const HOURS: u64 = 60 * MINUTES;
-const DAYS: u64 = 24 * HOURS;
-
-type DistributionMap = BTreeMap<Vec<(String, String)>, Summary>;
-
-#[derive(Clone)]
-pub struct MemoryCollector {
-    inner: Arc<Inner>,
-}
-
-struct Inner {
-    descriptions: RwLock<HashMap<String, metrics::SharedString>>,
-    distributions: RwLock<HashMap<String, DistributionMap>>,
-    recency: Recency<Key>,
-    registry: Registry<Key, GenerationalStorage<AtomicStorage>>,
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-struct Counter {
-    labels: BTreeMap<String, String>,
-    value: u64,
-}
-
-impl std::fmt::Display for Counter {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let labels = self
-            .labels
-            .iter()
-            .map(|(k, v)| format!("{}: {}", k, v))
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        write!(f, "{} - {}", labels, self.value)
-    }
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-struct Gauge {
-    labels: BTreeMap<String, String>,
-    value: f64,
-}
-
-impl std::fmt::Display for Gauge {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let labels = self
-            .labels
-            .iter()
-            .map(|(k, v)| format!("{}: {}", k, v))
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        write!(f, "{} - {}", labels, self.value)
-    }
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-struct Histogram {
-    labels: BTreeMap<String, String>,
-    value: Vec<(f64, Option<f64>)>,
-}
-
-impl std::fmt::Display for Histogram {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let labels = self
-            .labels
-            .iter()
-            .map(|(k, v)| format!("{}: {}", k, v))
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        let value = self
-            .value
-            .iter()
-            .map(|(k, v)| {
-                if let Some(v) = v {
-                    format!("{}: {:.6}", k, v)
-                } else {
-                    format!("{}: None,", k)
-                }
-            })
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        write!(f, "{} - {}", labels, value)
-    }
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-pub(crate) struct Snapshot {
-    counters: HashMap<String, Vec<Counter>>,
-    gauges: HashMap<String, Vec<Gauge>>,
-    histograms: HashMap<String, Vec<Histogram>>,
-}
-
-const PAIRS: [((&str, &str), &str); 2] = [
-    (
-        (
-            "background-jobs.worker.started",
-            "background-jobs.worker.finished",
-        ),
-        "background-jobs.worker.running",
-    ),
-    (
-        (
-            "background-jobs.job.started",
-            "background-jobs.job.finished",
-        ),
-        "background-jobs.job.running",
-    ),
-];
-
-#[derive(Default)]
-struct MergeCounter {
-    start: Option<Counter>,
-    finish: Option<Counter>,
-}
-
-impl MergeCounter {
-    fn merge(self) -> Option<Counter> {
-        match (self.start, self.finish) {
-            (Some(start), Some(end)) => Some(Counter {
-                labels: start.labels,
-                value: start.value.saturating_sub(end.value),
-            }),
-            (Some(only), None) => Some(only),
-            (None, Some(only)) => Some(Counter {
-                labels: only.labels,
-                value: 0,
-            }),
-            (None, None) => None,
-        }
-    }
-}
-
-impl Snapshot {
-    pub(crate) fn present(self) {
-        if !self.counters.is_empty() {
-            println!("Counters");
-            let mut merging = HashMap::new();
-            for (key, counters) in self.counters {
-                if let Some(((start, _), name)) = PAIRS
-                    .iter()
-                    .find(|((start, finish), _)| *start == key || *finish == key)
-                {
-                    let entry = merging.entry(name).or_insert_with(HashMap::new);
-
-                    for counter in counters {
-                        let mut merge_counter = entry
-                            .entry(counter.labels.clone())
-                            .or_insert_with(MergeCounter::default);
-                        if key == *start {
-                            merge_counter.start = Some(counter);
-                        } else {
-                            merge_counter.finish = Some(counter);
-                        }
-                    }
-
-                    continue;
-                }
-
-                println!("\t{}", key);
-                for counter in counters {
-                    println!("\t\t{}", counter);
-                }
-            }
-
-            for (key, counters) in merging {
-                println!("\t{}", key);
-
-                for (_, counter) in counters {
-                    if let Some(counter) = counter.merge() {
-                        println!("\t\t{}", counter);
-                    }
-                }
-            }
-        }
-
-        if !self.gauges.is_empty() {
-            println!("Gauges");
-            for (key, gauges) in self.gauges {
-                println!("\t{}", key);
-
-                for gauge in gauges {
-                    println!("\t\t{}", gauge);
-                }
-            }
-        }
-
-        if !self.histograms.is_empty() {
-            println!("Histograms");
-            for (key, histograms) in self.histograms {
-                println!("\t{}", key);
-
-                for histogram in histograms {
-                    println!("\t\t{}", histogram);
-                }
-            }
-        }
-    }
-}
-
-fn key_to_parts(key: &Key) -> (String, Vec<(String, String)>) {
-    let labels = key
-        .labels()
-        .into_iter()
-        .map(|label| (label.key().to_string(), label.value().to_string()))
-        .collect();
-    let name = key.name().to_string();
-    (name, labels)
-}
-
-impl Inner {
-    fn snapshot_counters(&self) -> HashMap<String, Vec<Counter>> {
-        let mut counters = HashMap::new();
-
-        for (key, counter) in self.registry.get_counter_handles() {
-            let gen = counter.get_generation();
-            if !self.recency.should_store_counter(&key, gen, &self.registry) {
-                continue;
-            }
-
-            let (name, labels) = key_to_parts(&key);
-            let value = counter.get_inner().load(Ordering::Acquire);
-            counters.entry(name).or_insert_with(Vec::new).push(Counter {
-                labels: labels.into_iter().collect(),
-                value,
-            });
-        }
-
-        counters
-    }
-
-    fn snapshot_gauges(&self) -> HashMap<String, Vec<Gauge>> {
-        let mut gauges = HashMap::new();
-
-        for (key, gauge) in self.registry.get_gauge_handles() {
-            let gen = gauge.get_generation();
-            if !self.recency.should_store_gauge(&key, gen, &self.registry) {
-                continue;
-            }
-
-            let (name, labels) = key_to_parts(&key);
-            let value = f64::from_bits(gauge.get_inner().load(Ordering::Acquire));
-            gauges.entry(name).or_insert_with(Vec::new).push(Gauge {
-                labels: labels.into_iter().collect(),
-                value,
-            })
-        }
-
-        gauges
-    }
-
-    fn snapshot_histograms(&self) -> HashMap<String, Vec<Histogram>> {
-        for (key, histogram) in self.registry.get_histogram_handles() {
-            let gen = histogram.get_generation();
-            let (name, labels) = key_to_parts(&key);
-
-            if !self
-                .recency
-                .should_store_histogram(&key, gen, &self.registry)
-            {
-                let mut d = self.distributions.write().unwrap();
-                let delete_by_name = if let Some(by_name) = d.get_mut(&name) {
-                    by_name.remove(&labels);
-                    by_name.is_empty()
-                } else {
-                    false
-                };
-                drop(d);
-
-                if delete_by_name {
-                    self.descriptions.write().unwrap().remove(&name);
-                }
-
-                continue;
-            }
-
-            let mut d = self.distributions.write().unwrap();
-            let outer_entry = d.entry(name.clone()).or_insert_with(BTreeMap::new);
-
-            let entry = outer_entry
-                .entry(labels)
-                .or_insert_with(Summary::with_defaults);
-
-            histogram.get_inner().clear_with(|samples| {
-                for sample in samples {
-                    entry.add(*sample);
-                }
-            })
-        }
-
-        let d = self.distributions.read().unwrap().clone();
-        d.into_iter()
-            .map(|(key, value)| {
-                (
-                    key,
-                    value
-                        .into_iter()
-                        .map(|(labels, summary)| Histogram {
-                            labels: labels.into_iter().collect(),
-                            value: [0.001, 0.01, 0.05, 0.1, 0.5, 0.9, 0.99, 1.0]
-                                .into_iter()
-                                .map(|q| (q, summary.quantile(q)))
-                                .collect(),
-                        })
-                        .collect(),
-                )
-            })
-            .collect()
-    }
-
-    fn snapshot(&self) -> Snapshot {
-        Snapshot {
-            counters: self.snapshot_counters(),
-            gauges: self.snapshot_gauges(),
-            histograms: self.snapshot_histograms(),
-        }
-    }
-}
-
-impl MemoryCollector {
-    pub(crate) fn new() -> Self {
-        MemoryCollector {
-            inner: Arc::new(Inner {
-                descriptions: Default::default(),
-                distributions: Default::default(),
-                recency: Recency::new(
-                    Clock::new(),
-                    MetricKindMask::ALL,
-                    Some(Duration::from_secs(5 * DAYS)),
-                ),
-                registry: Registry::new(GenerationalStorage::atomic()),
-            }),
-        }
-    }
-
-    pub(crate) fn install(&self) -> Result<(), SetRecorderError> {
-        metrics::set_boxed_recorder(Box::new(self.clone()))
-    }
-
-    pub(crate) fn snapshot(&self) -> Snapshot {
-        self.inner.snapshot()
-    }
-
-    fn add_description_if_missing(
-        &self,
-        key: &metrics::KeyName,
-        description: metrics::SharedString,
-    ) {
-        let mut d = self.inner.descriptions.write().unwrap();
-        d.entry(key.as_str().to_owned()).or_insert(description);
-    }
-}
-
-impl Recorder for MemoryCollector {
-    fn describe_counter(
-        &self,
-        key: metrics::KeyName,
-        _: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.add_description_if_missing(&key, description)
-    }
-
-    fn describe_gauge(
-        &self,
-        key: metrics::KeyName,
-        _: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.add_description_if_missing(&key, description)
-    }
-
-    fn describe_histogram(
-        &self,
-        key: metrics::KeyName,
-        _: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.add_description_if_missing(&key, description)
-    }
-
-    fn register_counter(&self, key: &Key) -> metrics::Counter {
-        self.inner
-            .registry
-            .get_or_create_counter(key, |c| c.clone().into())
-    }
-
-    fn register_gauge(&self, key: &Key) -> metrics::Gauge {
-        self.inner
-            .registry
-            .get_or_create_gauge(key, |c| c.clone().into())
-    }
-
-    fn register_histogram(&self, key: &Key) -> metrics::Histogram {
-        self.inner
-            .registry
-            .get_or_create_histogram(key, |c| c.clone().into())
-    }
-}
+pub(crate) use double::DoubleRecorder;
+pub(crate) use stats::{MemoryCollector, Snapshot};
diff --git a/src/collector/double.rs b/src/collector/double.rs
new file mode 100644
index 0000000..b78dbff
--- /dev/null
+++ b/src/collector/double.rs
@@ -0,0 +1,133 @@
+use metrics::{CounterFn, GaugeFn, HistogramFn, Key, Recorder, SetRecorderError};
+use std::sync::Arc;
+
+#[derive(Clone)]
+pub(crate) struct DoubleRecorder<R, S> {
+    first: R,
+    second: S,
+}
+
+struct DoubleCounter {
+    first: metrics::Counter,
+    second: metrics::Counter,
+}
+
+struct DoubleGauge {
+    first: metrics::Gauge,
+    second: metrics::Gauge,
+}
+
+struct DoubleHistogram {
+    first: metrics::Histogram,
+    second: metrics::Histogram,
+}
+
+impl<R, S> DoubleRecorder<R, S> {
+    pub(crate) fn new(first: R, second: S) -> Self {
+        DoubleRecorder { first, second }
+    }
+
+    pub(crate) fn install(self) -> Result<(), SetRecorderError>
+    where
+        R: Recorder + 'static,
+        S: Recorder + 'static,
+    {
+        metrics::set_boxed_recorder(Box::new(self))
+    }
+}
+
+impl<R, S> Recorder for DoubleRecorder<R, S>
+where
+    R: Recorder,
+    S: Recorder,
+{
+    fn describe_counter(
+        &self,
+        key: metrics::KeyName,
+        unit: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.first
+            .describe_counter(key.clone(), unit, description.clone());
+        self.second.describe_counter(key, unit, description);
+    }
+
+    fn describe_gauge(
+        &self,
+        key: metrics::KeyName,
+        unit: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.first
+            .describe_gauge(key.clone(), unit, description.clone());
+        self.second.describe_gauge(key, unit, description);
+    }
+
+    fn describe_histogram(
+        &self,
+        key: metrics::KeyName,
+        unit: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.first
+            .describe_histogram(key.clone(), unit, description.clone());
+        self.second.describe_histogram(key, unit, description);
+    }
+
+    fn register_counter(&self, key: &Key) -> metrics::Counter {
+        let first = self.first.register_counter(key);
+        let second = self.second.register_counter(key);
+
+        metrics::Counter::from_arc(Arc::new(DoubleCounter { first, second }))
+    }
+
+    fn register_gauge(&self, key: &Key) -> metrics::Gauge {
+        let first = self.first.register_gauge(key);
+        let second = self.second.register_gauge(key);
+
+        metrics::Gauge::from_arc(Arc::new(DoubleGauge { first, second }))
+    }
+
+    fn register_histogram(&self, key: &Key) -> metrics::Histogram {
+        let first = self.first.register_histogram(key);
+        let second = self.second.register_histogram(key);
+
+        metrics::Histogram::from_arc(Arc::new(DoubleHistogram { first, second }))
+    }
+}
+
+impl CounterFn for DoubleCounter {
+    fn increment(&self, value: u64) {
+        self.first.increment(value);
+        self.second.increment(value);
+    }
+
+    fn absolute(&self, value: u64) {
+        self.first.absolute(value);
+        self.second.absolute(value);
+    }
+}
+
+impl GaugeFn for DoubleGauge {
+    fn increment(&self, value: f64) {
+        self.first.increment(value);
+        self.second.increment(value);
+    }
+
+    fn decrement(&self, value: f64) {
+        self.first.decrement(value);
+        self.second.decrement(value);
+    }
+
+    fn set(&self, value: f64) {
+        self.first.set(value);
+        self.second.set(value);
+    }
+}
+
+impl HistogramFn for DoubleHistogram {
+    fn record(&self, value: f64) {
+        self.first.record(value);
+        self.second.record(value);
+    }
+}
diff --git a/src/collector/stats.rs b/src/collector/stats.rs
new file mode 100644
index 0000000..c8d1812
--- /dev/null
+++ b/src/collector/stats.rs
@@ -0,0 +1,414 @@
+use metrics::{Key, Recorder, SetRecorderError};
+use metrics_util::{
+    registry::{AtomicStorage, GenerationalStorage, Recency, Registry},
+    MetricKindMask, Summary,
+};
+use quanta::Clock;
+use std::{
+    collections::{BTreeMap, HashMap},
+    sync::{atomic::Ordering, Arc, RwLock},
+    time::Duration,
+};
+
+const SECONDS: u64 = 1;
+const MINUTES: u64 = 60 * SECONDS;
+const HOURS: u64 = 60 * MINUTES;
+const DAYS: u64 = 24 * HOURS;
+
+type DistributionMap = BTreeMap<Vec<(String, String)>, Summary>;
+
+#[derive(Clone)]
+pub struct MemoryCollector {
+    inner: Arc<Inner>,
+}
+
+struct Inner {
+    descriptions: RwLock<HashMap<String, metrics::SharedString>>,
+    distributions: RwLock<HashMap<String, DistributionMap>>,
+    recency: Recency<Key>,
+    registry: Registry<Key, GenerationalStorage<AtomicStorage>>,
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+struct Counter {
+    labels: BTreeMap<String, String>,
+    value: u64,
+}
+
+impl std::fmt::Display for Counter {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let labels = self
+            .labels
+            .iter()
+            .map(|(k, v)| format!("{}: {}", k, v))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        write!(f, "{} - {}", labels, self.value)
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+struct Gauge {
+    labels: BTreeMap<String, String>,
+    value: f64,
+}
+
+impl std::fmt::Display for Gauge {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let labels = self
+            .labels
+            .iter()
+            .map(|(k, v)| format!("{}: {}", k, v))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        write!(f, "{} - {}", labels, self.value)
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+struct Histogram {
+    labels: BTreeMap<String, String>,
+    value: Vec<(f64, Option<f64>)>,
+}
+
+impl std::fmt::Display for Histogram {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let labels = self
+            .labels
+            .iter()
+            .map(|(k, v)| format!("{}: {}", k, v))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        let value = self
+            .value
+            .iter()
+            .map(|(k, v)| {
+                if let Some(v) = v {
+                    format!("{}: {:.6}", k, v)
+                } else {
+                    format!("{}: None,", k)
+                }
+            })
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        write!(f, "{} - {}", labels, value)
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub(crate) struct Snapshot {
+    counters: HashMap<String, Vec<Counter>>,
+    gauges: HashMap<String, Vec<Gauge>>,
+    histograms: HashMap<String, Vec<Histogram>>,
+}
+
+const PAIRS: [((&str, &str), &str); 2] = [
+    (
+        (
+            "background-jobs.worker.started",
+            "background-jobs.worker.finished",
+        ),
+        "background-jobs.worker.running",
+    ),
+    (
+        (
+            "background-jobs.job.started",
+            "background-jobs.job.finished",
+        ),
+        "background-jobs.job.running",
+    ),
+];
+
+#[derive(Default)]
+struct MergeCounter {
+    start: Option<Counter>,
+    finish: Option<Counter>,
+}
+
+impl MergeCounter {
+    fn merge(self) -> Option<Counter> {
+        match (self.start, self.finish) {
+            (Some(start), Some(end)) => Some(Counter {
+                labels: start.labels,
+                value: start.value.saturating_sub(end.value),
+            }),
+            (Some(only), None) => Some(only),
+            (None, Some(only)) => Some(Counter {
+                labels: only.labels,
+                value: 0,
+            }),
+            (None, None) => None,
+        }
+    }
+}
+
+impl Snapshot {
+    pub(crate) fn present(self) {
+        if !self.counters.is_empty() {
+            println!("Counters");
+            let mut merging = HashMap::new();
+            for (key, counters) in self.counters {
+                if let Some(((start, _), name)) = PAIRS
+                    .iter()
+                    .find(|((start, finish), _)| *start == key || *finish == key)
+                {
+                    let entry = merging.entry(name).or_insert_with(HashMap::new);
+
+                    for counter in counters {
+                        let mut merge_counter = entry
+                            .entry(counter.labels.clone())
+                            .or_insert_with(MergeCounter::default);
+                        if key == *start {
+                            merge_counter.start = Some(counter);
+                        } else {
+                            merge_counter.finish = Some(counter);
+                        }
+                    }
+
+                    continue;
+                }
+
+                println!("\t{}", key);
+                for counter in counters {
+                    println!("\t\t{}", counter);
+                }
+            }
+
+            for (key, counters) in merging {
+                println!("\t{}", key);
+
+                for (_, counter) in counters {
+                    if let Some(counter) = counter.merge() {
+                        println!("\t\t{}", counter);
+                    }
+                }
+            }
+        }
+
+        if !self.gauges.is_empty() {
+            println!("Gauges");
+            for (key, gauges) in self.gauges {
+                println!("\t{}", key);
+
+                for gauge in gauges {
+                    println!("\t\t{}", gauge);
+                }
+            }
+        }
+
+        if !self.histograms.is_empty() {
+            println!("Histograms");
+            for (key, histograms) in self.histograms {
+                println!("\t{}", key);
+
+                for histogram in histograms {
+                    println!("\t\t{}", histogram);
+                }
+            }
+        }
+    }
+}
+
+fn key_to_parts(key: &Key) -> (String, Vec<(String, String)>) {
+    let labels = key
+        .labels()
+        .into_iter()
+        .map(|label| (label.key().to_string(), label.value().to_string()))
+        .collect();
+    let name = key.name().to_string();
+    (name, labels)
+}
+
+impl Inner {
+    fn snapshot_counters(&self) -> HashMap<String, Vec<Counter>> {
+        let mut counters = HashMap::new();
+
+        for (key, counter) in self.registry.get_counter_handles() {
+            let gen = counter.get_generation();
+            if !self.recency.should_store_counter(&key, gen, &self.registry) {
+                continue;
+            }
+
+            let (name, labels) = key_to_parts(&key);
+            let value = counter.get_inner().load(Ordering::Acquire);
+            counters.entry(name).or_insert_with(Vec::new).push(Counter {
+                labels: labels.into_iter().collect(),
+                value,
+            });
+        }
+
+        counters
+    }
+
+    fn snapshot_gauges(&self) -> HashMap<String, Vec<Gauge>> {
+        let mut gauges = HashMap::new();
+
+        for (key, gauge) in self.registry.get_gauge_handles() {
+            let gen = gauge.get_generation();
+            if !self.recency.should_store_gauge(&key, gen, &self.registry) {
+                continue;
+            }
+
+            let (name, labels) = key_to_parts(&key);
+            let value = f64::from_bits(gauge.get_inner().load(Ordering::Acquire));
+            gauges.entry(name).or_insert_with(Vec::new).push(Gauge {
+                labels: labels.into_iter().collect(),
+                value,
+            })
+        }
+
+        gauges
+    }
+
+    fn snapshot_histograms(&self) -> HashMap<String, Vec<Histogram>> {
+        for (key, histogram) in self.registry.get_histogram_handles() {
+            let gen = histogram.get_generation();
+            let (name, labels) = key_to_parts(&key);
+
+            if !self
+                .recency
+                .should_store_histogram(&key, gen, &self.registry)
+            {
+                let mut d = self.distributions.write().unwrap();
+                let delete_by_name = if let Some(by_name) = d.get_mut(&name) {
+                    by_name.remove(&labels);
+                    by_name.is_empty()
+                } else {
+                    false
+                };
+                drop(d);
+
+                if delete_by_name {
+                    self.descriptions.write().unwrap().remove(&name);
+                }
+
+                continue;
+            }
+
+            let mut d = self.distributions.write().unwrap();
+            let outer_entry = d.entry(name.clone()).or_insert_with(BTreeMap::new);
+
+            let entry = outer_entry
+                .entry(labels)
+                .or_insert_with(Summary::with_defaults);
+
+            histogram.get_inner().clear_with(|samples| {
+                for sample in samples {
+                    entry.add(*sample);
+                }
+            })
+        }
+
+        let d = self.distributions.read().unwrap().clone();
+        d.into_iter()
+            .map(|(key, value)| {
+                (
+                    key,
+                    value
+                        .into_iter()
+                        .map(|(labels, summary)| Histogram {
+                            labels: labels.into_iter().collect(),
+                            value: [0.001, 0.01, 0.05, 0.1, 0.5, 0.9, 0.99, 1.0]
+                                .into_iter()
+                                .map(|q| (q, summary.quantile(q)))
+                                .collect(),
+                        })
+                        .collect(),
+                )
+            })
+            .collect()
+    }
+
+    fn snapshot(&self) -> Snapshot {
+        Snapshot {
+            counters: self.snapshot_counters(),
+            gauges: self.snapshot_gauges(),
+            histograms: self.snapshot_histograms(),
+        }
+    }
+}
+
+impl MemoryCollector {
+    pub(crate) fn new() -> Self {
+        MemoryCollector {
+            inner: Arc::new(Inner {
+                descriptions: Default::default(),
+                distributions: Default::default(),
+                recency: Recency::new(
+                    Clock::new(),
+                    MetricKindMask::ALL,
+                    Some(Duration::from_secs(5 * DAYS)),
+                ),
+                registry: Registry::new(GenerationalStorage::atomic()),
+            }),
+        }
+    }
+
+    pub(crate) fn snapshot(&self) -> Snapshot {
+        self.inner.snapshot()
+    }
+
+    fn add_description_if_missing(
+        &self,
+        key: &metrics::KeyName,
+        description: metrics::SharedString,
+    ) {
+        let mut d = self.inner.descriptions.write().unwrap();
+        d.entry(key.as_str().to_owned()).or_insert(description);
+    }
+
+    pub(crate) fn install(&self) -> Result<(), SetRecorderError> {
+        metrics::set_boxed_recorder(Box::new(self.clone()))
+    }
+}
+
+impl Recorder for MemoryCollector {
+    fn describe_counter(
+        &self,
+        key: metrics::KeyName,
+        _: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.add_description_if_missing(&key, description)
+    }
+
+    fn describe_gauge(
+        &self,
+        key: metrics::KeyName,
+        _: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.add_description_if_missing(&key, description)
+    }
+
+    fn describe_histogram(
+        &self,
+        key: metrics::KeyName,
+        _: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.add_description_if_missing(&key, description)
+    }
+
+    fn register_counter(&self, key: &Key) -> metrics::Counter {
+        self.inner
+            .registry
+            .get_or_create_counter(key, |c| c.clone().into())
+    }
+
+    fn register_gauge(&self, key: &Key) -> metrics::Gauge {
+        self.inner
+            .registry
+            .get_or_create_gauge(key, |c| c.clone().into())
+    }
+
+    fn register_histogram(&self, key: &Key) -> metrics::Histogram {
+        self.inner
+            .registry
+            .get_or_create_histogram(key, |c| c.clone().into())
+    }
+}
diff --git a/src/config.rs b/src/config.rs
index bd70162..52657cf 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -14,7 +14,11 @@ use config::Environment;
 use http_signature_normalization_actix::prelude::VerifyDigest;
 use rustls::{Certificate, PrivateKey};
 use sha2::{Digest, Sha256};
-use std::{io::BufReader, net::IpAddr, path::PathBuf};
+use std::{
+    io::BufReader,
+    net::{IpAddr, SocketAddr},
+    path::PathBuf,
+};
 use uuid::Uuid;
 
 #[derive(Clone, Debug, serde::Deserialize)]
@@ -38,6 +42,8 @@ pub(crate) struct ParsedConfig {
     footer_blurb: Option<String>,
     local_domains: Option<String>,
     local_blurb: Option<String>,
+    prometheus_addr: Option<IpAddr>,
+    prometheus_port: Option<u16>,
 }
 
 #[derive(Clone)]
@@ -60,6 +66,7 @@ pub struct Config {
     footer_blurb: Option<String>,
     local_domains: Vec<String>,
     local_blurb: Option<String>,
+    prometheus_config: Option<PrometheusConfig>,
 }
 
 #[derive(Clone)]
@@ -68,6 +75,12 @@ struct TlsConfig {
     cert: PathBuf,
 }
 
+#[derive(Clone, Debug)]
+struct PrometheusConfig {
+    addr: IpAddr,
+    port: u16,
+}
+
 #[derive(Debug)]
 pub enum UrlKind {
     Activity,
@@ -120,6 +133,7 @@ impl std::fmt::Debug for Config {
             .field("footer_blurb", &self.footer_blurb)
             .field("local_domains", &self.local_domains)
             .field("local_blurb", &self.local_blurb)
+            .field("prometheus_config", &self.prometheus_config)
             .finish()
     }
 }
@@ -146,6 +160,8 @@ impl Config {
             .set_default("footer_blurb", None as Option<&str>)?
             .set_default("local_domains", None as Option<&str>)?
             .set_default("local_blurb", None as Option<&str>)?
+            .set_default("prometheus_addr", None as Option<&str>)?
+            .set_default("prometheus_port", None as Option<u16>)?
             .add_source(Environment::default())
             .build()?;
 
@@ -174,6 +190,19 @@ impl Config {
             .map(|d| d.to_string())
             .collect();
 
+        let prometheus_config = match (config.prometheus_addr, config.prometheus_port) {
+            (Some(addr), Some(port)) => Some(PrometheusConfig { addr, port }),
+            (Some(_), None) => {
+                tracing::warn!("PROMETHEUS_ADDR is set but PROMETHEUS_PORT is not set, not building Prometheus config");
+                None
+            }
+            (None, Some(_)) => {
+                tracing::warn!("PROMETHEUS_PORT is set but PROMETHEUS_ADDR is not set, not building Prometheus config");
+                None
+            }
+            (None, None) => None,
+        };
+
         Ok(Config {
             hostname: config.hostname,
             addr: config.addr,
@@ -193,9 +222,16 @@ impl Config {
             footer_blurb: config.footer_blurb,
             local_domains,
             local_blurb: config.local_blurb,
+            prometheus_config,
         })
     }
 
+    pub(crate) fn prometheus_bind_address(&self) -> Option<SocketAddr> {
+        let config = self.prometheus_config.as_ref()?;
+
+        Some((config.addr, config.port).into())
+    }
+
     pub(crate) fn open_keys(&self) -> Result<Option<(Vec<Certificate>, PrivateKey)>, Error> {
         let tls = if let Some(tls) = &self.tls {
             tls
diff --git a/src/main.rs b/src/main.rs
index dccd8bb..f9976cf 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,10 +4,11 @@
 use activitystreams::iri_string::types::IriString;
 use actix_rt::task::JoinHandle;
 use actix_web::{middleware::Compress, web, App, HttpServer};
-use collector::MemoryCollector;
+use collector::{DoubleRecorder, MemoryCollector};
 #[cfg(feature = "console")]
 use console_subscriber::ConsoleLayer;
 use http_signature_normalization_actix::middleware::VerifySignature;
+use metrics_exporter_prometheus::PrometheusBuilder;
 use opentelemetry::{sdk::Resource, KeyValue};
 use opentelemetry_otlp::WithExportConfig;
 use rustls::ServerConfig;
@@ -103,8 +104,19 @@ async fn main() -> Result<(), anyhow::Error> {
     let config = Config::build()?;
 
     init_subscriber(Config::software_name(), config.opentelemetry_url())?;
+
     let collector = MemoryCollector::new();
-    collector.install()?;
+
+    if let Some(bind_addr) = config.prometheus_bind_address() {
+        let (recorder, exporter) = PrometheusBuilder::new()
+            .with_http_listener(bind_addr)
+            .build()?;
+
+        actix_rt::spawn(exporter);
+        DoubleRecorder::new(recorder, collector.clone()).install()?;
+    } else {
+        collector.install()?;
+    }
 
     let args = Args::new();
 

From d4e51a1afa2c92fcaf26bf5890c1e02789f3ed42 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 26 Dec 2022 11:20:02 -0600
Subject: [PATCH 44/87] Add scrape endpoint to .env

---
 .env | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.env b/.env
index f9b3b94..0212bdc 100644
--- a/.env
+++ b/.env
@@ -9,3 +9,5 @@ FOOTER_BLURB="Contact <a href=\"https://masto.asonix.dog/@asonix\">@asonix</a> f
 LOCAL_DOMAINS="masto.asonix.dog"
 LOCAL_BLURB="<p>Welcome to my cool relay where I have cool relay things happening. I hope you enjoy your stay!</p>"
 # OPENTELEMETRY_URL=http://localhost:4317
+PROMETHEUS_ADDR=127.0.0.1
+PROMETHEUS_PORT=9000

From 5f5c34640f9a568b46fabae20210edf41e31c978 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 1 Jan 2023 09:46:44 -0600
Subject: [PATCH 45/87] Apply patch from perillamint on github

use git hash to describe version number
---
 src/build.rs  | 1 +
 src/config.rs | 6 +++++-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/src/build.rs b/src/build.rs
index 1c7e714..ebac904 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -6,6 +6,7 @@ fn git_info() {
         if output.status.success() {
             let git_hash = String::from_utf8_lossy(&output.stdout);
             println!("cargo:rustc-env=GIT_HASH={}", git_hash);
+            println!("cargo:rustc-env=GIT_SHORT_HASH={}", &git_hash[..8])
         }
     }
 
diff --git a/src/config.rs b/src/config.rs
index 52657cf..badf9ec 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -367,7 +367,7 @@ impl Config {
 
     fn git_version() -> Option<String> {
         let branch = Self::git_branch()?;
-        let hash = Self::git_hash()?;
+        let hash = Self::git_short_hash()?;
 
         Some(format!("{}-{}", branch, hash))
     }
@@ -388,6 +388,10 @@ impl Config {
         option_env!("GIT_HASH")
     }
 
+    fn git_short_hash() -> Option<&'static str> {
+        option_env!("GIT_SHORT_HASH")
+    }
+
     pub(crate) fn user_agent(&self) -> String {
         format!(
             "{} ({}/{}; +{})",

From f291b24269e24ebdc1b832db83babc431343c6f1 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 1 Jan 2023 09:47:21 -0600
Subject: [PATCH 46/87] Apply patch from perillamint on github

Show repository URL with commit reference
---
 src/config.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/config.rs b/src/config.rs
index badf9ec..ae795a7 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -58,6 +58,7 @@ pub struct Config {
     base_uri: IriAbsoluteString,
     sled_path: PathBuf,
     source_repo: IriString,
+    source_url: IriString,
     opentelemetry_url: Option<IriString>,
     telegram_token: Option<String>,
     telegram_admin_handle: Option<String>,
@@ -203,6 +204,11 @@ impl Config {
             (None, None) => None,
         };
 
+        let source_url = match Self::git_hash() {
+            Some(hash) => format!("{}/tree/{}", config.source_repo, hash).parse().unwrap(),
+            None => config.source_repo.clone()
+        };
+
         Ok(Config {
             hostname: config.hostname,
             addr: config.addr,
@@ -214,6 +220,7 @@ impl Config {
             base_uri,
             sled_path: config.sled_path,
             source_repo: config.source_repo,
+            source_url,
             opentelemetry_url: config.opentelemetry_url,
             telegram_token: config.telegram_token,
             telegram_admin_handle: config.telegram_admin_handle,
@@ -403,7 +410,7 @@ impl Config {
     }
 
     pub(crate) fn source_code(&self) -> &IriString {
-        &self.source_repo
+        &self.source_url
     }
 
     pub(crate) fn opentelemetry_url(&self) -> Option<&IriString> {

From 5faeaf6371651c336896ba698e05e0fb031c8ff2 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 1 Jan 2023 10:01:39 -0600
Subject: [PATCH 47/87] Revert "Apply patch from perillamint on github"

This reverts commit f291b24269e24ebdc1b832db83babc431343c6f1.
---
 src/config.rs | 9 +--------
 1 file changed, 1 insertion(+), 8 deletions(-)

diff --git a/src/config.rs b/src/config.rs
index ae795a7..badf9ec 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -58,7 +58,6 @@ pub struct Config {
     base_uri: IriAbsoluteString,
     sled_path: PathBuf,
     source_repo: IriString,
-    source_url: IriString,
     opentelemetry_url: Option<IriString>,
     telegram_token: Option<String>,
     telegram_admin_handle: Option<String>,
@@ -204,11 +203,6 @@ impl Config {
             (None, None) => None,
         };
 
-        let source_url = match Self::git_hash() {
-            Some(hash) => format!("{}/tree/{}", config.source_repo, hash).parse().unwrap(),
-            None => config.source_repo.clone()
-        };
-
         Ok(Config {
             hostname: config.hostname,
             addr: config.addr,
@@ -220,7 +214,6 @@ impl Config {
             base_uri,
             sled_path: config.sled_path,
             source_repo: config.source_repo,
-            source_url,
             opentelemetry_url: config.opentelemetry_url,
             telegram_token: config.telegram_token,
             telegram_admin_handle: config.telegram_admin_handle,
@@ -410,7 +403,7 @@ impl Config {
     }
 
     pub(crate) fn source_code(&self) -> &IriString {
-        &self.source_url
+        &self.source_repo
     }
 
     pub(crate) fn opentelemetry_url(&self) -> Option<&IriString> {

From f5fed2fce167bcd5613d984da72b0dd3ee0d8153 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 1 Jan 2023 10:19:11 -0600
Subject: [PATCH 48/87] Apply patch from perillamint on github

One missing bit Debug implementation for source_url
---
 src/config.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/config.rs b/src/config.rs
index badf9ec..f22cd05 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -121,6 +121,7 @@ impl std::fmt::Debug for Config {
             .field("base_uri", &self.base_uri.to_string())
             .field("sled_path", &self.sled_path)
             .field("source_repo", &self.source_repo.to_string())
+            .field("source_url", &self.source_url.to_string())
             .field(
                 "opentelemetry_url",
                 &self.opentelemetry_url.as_ref().map(|url| url.to_string()),

From 3a14242a917321e5a4232c89ccada5312062e22f Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 1 Jan 2023 10:28:52 -0600
Subject: [PATCH 49/87] Apply patch from perillamint on github

Accept REPOSITORY_COMMIT_BASE envvar to build repository url
---
 src/config.rs | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/src/config.rs b/src/config.rs
index f22cd05..848cc5b 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -33,6 +33,7 @@ pub(crate) struct ParsedConfig {
     publish_blocks: bool,
     sled_path: PathBuf,
     source_repo: IriString,
+    repository_commit_base: String,
     opentelemetry_url: Option<IriString>,
     telegram_token: Option<String>,
     telegram_admin_handle: Option<String>,
@@ -121,7 +122,6 @@ impl std::fmt::Debug for Config {
             .field("base_uri", &self.base_uri.to_string())
             .field("sled_path", &self.sled_path)
             .field("source_repo", &self.source_repo.to_string())
-            .field("source_url", &self.source_url.to_string())
             .field(
                 "opentelemetry_url",
                 &self.opentelemetry_url.as_ref().map(|url| url.to_string()),
@@ -152,6 +152,7 @@ impl Config {
             .set_default("publish_blocks", false)?
             .set_default("sled_path", "./sled/db-0-34")?
             .set_default("source_repo", "https://git.asonix.dog/asonix/relay")?
+            .set_default("repository_commit_base", "/src/commit/")?
             .set_default("opentelemetry_url", None as Option<&str>)?
             .set_default("telegram_token", None as Option<&str>)?
             .set_default("telegram_admin_handle", None as Option<&str>)?
@@ -204,6 +205,16 @@ impl Config {
             (None, None) => None,
         };
 
+        let source_url = match Self::git_hash() {
+            Some(hash) => format!(
+                "{}{}{}",
+                config.source_repo, config.repository_commit_base, hash
+            )
+            .parse()
+            .expect("constructed source URL is valid"),
+            None => config.source_repo.clone(),
+        };
+
         Ok(Config {
             hostname: config.hostname,
             addr: config.addr,
@@ -214,7 +225,7 @@ impl Config {
             publish_blocks: config.publish_blocks,
             base_uri,
             sled_path: config.sled_path,
-            source_repo: config.source_repo,
+            source_repo: source_url,
             opentelemetry_url: config.opentelemetry_url,
             telegram_token: config.telegram_token,
             telegram_admin_handle: config.telegram_admin_handle,

From b6a10c4e652da3633c6b8824ec8f08aa7676b0ce Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 1 Jan 2023 10:29:28 -0600
Subject: [PATCH 50/87] Apply patch from perillamint on github

Document REPOSITORY_COMMIT_BASE envvar
---
 README.md | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/README.md b/README.md
index dfa6356..4e0f8e2 100644
--- a/README.md
+++ b/README.md
@@ -130,6 +130,8 @@ Where to store the on-disk database of connected servers. This defaults to `./sl
 The log level to print. Available levels are `ERROR`, `WARN`, `INFO`, `DEBUG`, and `TRACE`. You can also specify module paths to enable some logs but not others, such as `RUST_LOG=warn,tracing_actix_web=info,relay=info`. This defaults to `warn`
 ##### `SOURCE_REPO`
 The URL to the source code for the relay. This defaults to `https://git.asonix.dog/asonix/relay`, but should be changed if you're running a fork hosted elsewhere.
+##### `REPOSITORY_COMMIT_BASE`
+The base path of the repository commit hash reference. For example, `/src/commit/` for Gitea, `/tree/` for GitLab.
 ##### `API_TOKEN`
 The Secret token used to access the admin APIs. This must be set for the commandline to function
 ##### `OPENTELEMETRY_URL`

From f0a886292242c83ce3ace976fe9e4427d99bdb87 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 2 Jan 2023 12:43:27 -0600
Subject: [PATCH 51/87] Don't prometheus exporter for relay client

---
 Cargo.lock  | 110 +++++++++++++++++++++++++++++++---------------------
 Cargo.toml  |   2 +-
 src/main.rs |  12 +++---
 3 files changed, 72 insertions(+), 52 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 008efcf..6dcac36 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -65,7 +65,7 @@ dependencies = [
  "actix-service",
  "actix-tls",
  "actix-utils",
- "ahash",
+ "ahash 0.7.6",
  "base64",
  "bitflags",
  "brotli",
@@ -197,7 +197,7 @@ dependencies = [
  "actix-service",
  "actix-tls",
  "actix-utils",
- "ahash",
+ "ahash 0.7.6",
  "bytes",
  "bytestring",
  "cfg-if",
@@ -253,6 +253,17 @@ dependencies = [
  "version_check",
 ]
 
+[[package]]
+name = "ahash"
+version = "0.8.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+ "version_check",
+]
+
 [[package]]
 name = "aho-corasick"
 version = "0.7.20"
@@ -370,9 +381,9 @@ dependencies = [
 
 [[package]]
 name = "arc-swap"
-version = "1.5.1"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "983cd8b9d4b02a6dc6ffa557262eb5858a27a0038ffffe21a0f133eaa819a164"
+checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
 
 [[package]]
 name = "arrayvec"
@@ -430,7 +441,7 @@ dependencies = [
  "actix-service",
  "actix-tls",
  "actix-utils",
- "ahash",
+ "ahash 0.7.6",
  "base64",
  "bytes",
  "cfg-if",
@@ -697,9 +708,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.0.30"
+version = "4.0.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "656ad1e55e23d287773f7d8192c300dc715c3eeded93b3da651d11c42cfd74d2"
+checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
 dependencies = [
  "bitflags",
  "clap_derive",
@@ -741,7 +752,7 @@ dependencies = [
  "async-trait",
  "json5",
  "lazy_static",
- "nom 7.1.1",
+ "nom 7.1.2",
  "pathdiff",
  "ron",
  "rust-ini",
@@ -912,7 +923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc"
 dependencies = [
  "cfg-if",
- "hashbrown",
+ "hashbrown 0.12.3",
  "lock_api",
  "once_cell",
  "parking_lot_core 0.9.5",
@@ -1242,7 +1253,16 @@ version = "0.12.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
 dependencies = [
- "ahash",
+ "ahash 0.7.6",
+]
+
+[[package]]
+name = "hashbrown"
+version = "0.13.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
+dependencies = [
+ "ahash 0.8.2",
 ]
 
 [[package]]
@@ -1254,7 +1274,7 @@ dependencies = [
  "base64",
  "byteorder",
  "flate2",
- "nom 7.1.1",
+ "nom 7.1.2",
  "num-traits",
 ]
 
@@ -1435,7 +1455,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
 dependencies = [
  "autocfg",
- "hashbrown",
+ "hashbrown 0.12.3",
 ]
 
 [[package]]
@@ -1568,9 +1588,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.138"
+version = "0.2.139"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db6d7e329c562c5dfab7a46a2afabc8b987ab9a4834c9d1ca04dc54c1546cef8"
+checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
 
 [[package]]
 name = "libm"
@@ -1629,11 +1649,11 @@ dependencies = [
 
 [[package]]
 name = "lru"
-version = "0.8.1"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6e8aaa3f231bb4bd57b84b2d5dc3ae7f350265df8aa96492e0bc394a1571909"
+checksum = "71e7d46de488603ffdd5f30afbc64fbba2378214a2c3a2fb83abf3d33126df17"
 dependencies = [
- "hashbrown",
+ "hashbrown 0.13.1",
 ]
 
 [[package]]
@@ -1713,7 +1733,7 @@ version = "0.20.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849"
 dependencies = [
- "ahash",
+ "ahash 0.7.6",
  "metrics-macros",
  "portable-atomic",
 ]
@@ -1756,7 +1776,7 @@ dependencies = [
  "aho-corasick",
  "crossbeam-epoch",
  "crossbeam-utils",
- "hashbrown",
+ "hashbrown 0.12.3",
  "indexmap",
  "metrics",
  "num_cpus",
@@ -1876,9 +1896,9 @@ dependencies = [
 
 [[package]]
 name = "nom"
-version = "7.1.1"
+version = "7.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8903e5a29a317527874d0402f867152a3d21c908bb0b933e416c65e301d4c36"
+checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c"
 dependencies = [
  "memchr",
  "minimal-lexical",
@@ -1892,7 +1912,7 @@ checksum = "37794436ca3029a3089e0b95d42da1f0b565ad271e4d3bb4bad0c7bb70b10605"
 dependencies = [
  "bytecount",
  "memchr",
- "nom 7.1.1",
+ "nom 7.1.2",
 ]
 
 [[package]]
@@ -1988,9 +2008,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.16.0"
+version = "1.17.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860"
+checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
 
 [[package]]
 name = "opentelemetry"
@@ -2088,7 +2108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ccd746e37177e1711c20dd619a1620f34f5c8b569c53590a72dedd5344d8924a"
 dependencies = [
  "dlv-list",
- "hashbrown",
+ "hashbrown 0.12.3",
 ]
 
 [[package]]
@@ -2191,9 +2211,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.5.1"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc8bed3549e0f9b0a2a78bf7c0018237a2cdf085eecbbc048e52612438e4e9d0"
+checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2201,9 +2221,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.1"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cdc078600d06ff90d4ed238f0119d84ab5d43dbaad278b0e33a8820293b32344"
+checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2211,9 +2231,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.1"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28a1af60b1c4148bb269006a750cff8e2ea36aff34d2d96cf7be0b14d1bed23c"
+checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2224,9 +2244,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.5.1"
+version = "2.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fec8605d59fc2ae0c6c1aefc0c7c7a9769732017c0ce07f7a9cfffa7b4404f20"
+checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065"
 dependencies = [
  "once_cell",
  "pest",
@@ -2337,9 +2357,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "0.3.18"
+version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81bdd679d533107e090c2704a35982fc06302e30898e63ffa26a81155c012e92"
+checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b"
 
 [[package]]
 name = "ppv-lite86"
@@ -2693,7 +2713,7 @@ dependencies = [
  "arc-swap",
  "fastrand",
  "lazy_static",
- "nom 7.1.1",
+ "nom 7.1.2",
  "nom_locate",
  "num-bigint",
  "num-integer",
@@ -2713,7 +2733,7 @@ dependencies = [
  "itertools 0.10.5",
  "md5",
  "mime",
- "nom 7.1.1",
+ "nom 7.1.2",
  "rsass",
 ]
 
@@ -2738,9 +2758,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.5"
+version = "0.36.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3807b5d10909833d3e9acd1eb5fb988f79376ff10fce42937de71a449c4c588"
+checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
 dependencies = [
  "bitflags",
  "errno",
@@ -2807,18 +2827,18 @@ checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
 
 [[package]]
 name = "serde"
-version = "1.0.151"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97fed41fc1a24994d044e6db6935e69511a1153b52c15eb42493b26fa87feba0"
+checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.151"
+version = "1.0.152"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "255abe9a125a985c05190d687b320c12f9b1f0b99445e608c21ba0782c719ad8"
+checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3429,9 +3449,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7488d9441c630ea4cbde433aaccf00749ff306ffe1fda1cf13dfb06c85aceecd"
+checksum = "d16c2a0c52b267d46ea9a46012a28b3513ce166c28eaeaa875829ed2f8debd19"
 dependencies = [
  "actix-web",
  "pin-project",
diff --git a/Cargo.toml b/Cargo.toml
index a8705cd..c0320d6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -41,7 +41,7 @@ console-subscriber = { version = "0.1", optional = true }
 dashmap = "5.1.0"
 dotenv = "0.15.0"
 futures-util = "0.3.17"
-lru = "0.8.0"
+lru = "0.9.0"
 metrics = "0.20.1"
 metrics-exporter-prometheus = { version = "0.11.0", default-features = false, features = [
   "http-listener",
diff --git a/src/main.rs b/src/main.rs
index f9976cf..39bba1d 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -105,6 +105,12 @@ async fn main() -> Result<(), anyhow::Error> {
 
     init_subscriber(Config::software_name(), config.opentelemetry_url())?;
 
+    let args = Args::new();
+
+    if args.any() {
+        return client_main(config, args).await?;
+    }
+
     let collector = MemoryCollector::new();
 
     if let Some(bind_addr) = config.prometheus_bind_address() {
@@ -118,12 +124,6 @@ async fn main() -> Result<(), anyhow::Error> {
         collector.install()?;
     }
 
-    let args = Args::new();
-
-    if args.any() {
-        return client_main(config, args).await?;
-    }
-
     tracing::warn!("Opening DB");
     let db = Db::build(&config)?;
 

From 4998cd3a569dda313f200b6897a491c70b39490d Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 2 Jan 2023 12:43:51 -0600
Subject: [PATCH 52/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 6dcac36..fa0b763 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -309,7 +309,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.78"
+version = "0.3.79"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index c0320d6..e61fa5f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.78"
+version = "0.3.79"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 5488acb59df63992b45db3c7783995e8bd2e7185 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Tue, 3 Jan 2023 15:17:56 -0600
Subject: [PATCH 53/87] Fix docker volume mount in readme

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 4e0f8e2..ac22793 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@ _A simple and efficient activitypub relay_
 If running docker, you can start the relay with the following command:
 ```
 $ sudo docker run --rm -it \
-    -v "./:/mnt/" \
+    -v "$(pwd):/mnt/" \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \

From 662620be4632656b2c6dcb32a440f0d11bb9bf6b Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 23 Jan 2023 08:29:32 -0600
Subject: [PATCH 54/87] Only show open_registrations: false when restricted
 mode is enabled

---
 src/routes/nodeinfo.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/routes/nodeinfo.rs b/src/routes/nodeinfo.rs
index a504496..66785e0 100644
--- a/src/routes/nodeinfo.rs
+++ b/src/routes/nodeinfo.rs
@@ -44,6 +44,8 @@ pub(crate) async fn route(
         .map(|s| s.to_owned())
         .collect();
 
+    let open_registrations = !config.restricted_mode();
+
     web::Json(NodeInfo {
         version: NodeInfoVersion,
         software: Software {
@@ -55,7 +57,7 @@ pub(crate) async fn route(
             inbound: vec![],
             outbound: vec![],
         },
-        open_registrations: false,
+        open_registrations,
         usage: Usage {
             users: Users {
                 total: 1,

From 9cdebeae4cb9d159be3bcc9d548e2ade75073a42 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 23 Jan 2023 08:38:55 -0600
Subject: [PATCH 55/87] Update base64, ructe

---
 Cargo.lock                 | 374 ++++++++++++++++---------------------
 Cargo.toml                 |   4 +-
 src/middleware/verifier.rs |   3 +-
 src/requests.rs            |   3 +-
 src/routes/index.rs        |   2 +-
 templates/index.rs.html    |  10 +-
 templates/instance.rs.html |   4 +-
 7 files changed, 173 insertions(+), 227 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index fa0b763..68428c3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -56,9 +56,9 @@ dependencies = [
 
 [[package]]
 name = "actix-http"
-version = "3.2.2"
+version = "3.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c83abf9903e1f0ad9973cc4f7b9767fd5a03a583f51a5b7a339e07987cd2724"
+checksum = "0070905b2c4a98d184c4e81025253cb192aa8a73827553f38e9410801ceb35bb"
 dependencies = [
  "actix-codec",
  "actix-rt",
@@ -66,7 +66,7 @@ dependencies = [
  "actix-tls",
  "actix-utils",
  "ahash 0.7.6",
- "base64",
+ "base64 0.21.0",
  "bitflags",
  "brotli",
  "bytes",
@@ -88,6 +88,8 @@ dependencies = [
  "rand",
  "sha1",
  "smallvec",
+ "tokio",
+ "tokio-util",
  "tracing",
 ]
 
@@ -116,9 +118,9 @@ dependencies = [
 
 [[package]]
 name = "actix-rt"
-version = "2.7.0"
+version = "2.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ea16c295198e958ef31930a6ef37d0fb64e9ca3b6116e6b93a8bdae96ee1000"
+checksum = "15265b6b8e2347670eb363c47fc8c75208b4a4994b27192f345fcbe707804f3e"
 dependencies = [
  "actix-macros",
  "futures-core",
@@ -127,9 +129,9 @@ dependencies = [
 
 [[package]]
 name = "actix-server"
-version = "2.1.1"
+version = "2.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0da34f8e659ea1b077bb4637948b815cd3768ad5a188fdcd74ff4d84240cd824"
+checksum = "3e8613a75dd50cc45f473cee3c34d59ed677c0f7b44480ce3b8247d7dc519327"
 dependencies = [
  "actix-rt",
  "actix-service",
@@ -185,9 +187,9 @@ dependencies = [
 
 [[package]]
 name = "actix-web"
-version = "4.2.1"
+version = "4.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d48f7b6534e06c7bfc72ee91db7917d4af6afe23e7d223b51e68fffbb21e96b9"
+checksum = "464e0fddc668ede5f26ec1f9557a8d44eda948732f40c6b0ad79126930eb775f"
 dependencies = [
  "actix-codec",
  "actix-http",
@@ -320,7 +322,7 @@ dependencies = [
  "anyhow",
  "awc",
  "background-jobs",
- "base64",
+ "base64 0.21.0",
  "bcrypt",
  "clap",
  "config",
@@ -385,12 +387,6 @@ version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
 
-[[package]]
-name = "arrayvec"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
-
 [[package]]
 name = "async-stream"
 version = "0.3.3"
@@ -414,9 +410,9 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.60"
+version = "0.1.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "677d1d8ab452a3936018a687b20e6f7cf5363d713b732b8884001317b0e48aa3"
+checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -431,9 +427,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "awc"
-version = "3.0.1"
+version = "3.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "80ca7ff88063086d2e2c70b9f3b29b2fcd999bac68ac21731e66781970d68519"
+checksum = "0dff3fc64a176e0d4398c71b0f2c2679ff4a723c6ed8fcc68dfe5baa00665388"
 dependencies = [
  "actix-codec",
  "actix-http",
@@ -442,7 +438,7 @@ dependencies = [
  "actix-tls",
  "actix-utils",
  "ahash 0.7.6",
- "base64",
+ "base64 0.21.0",
  "bytes",
  "cfg-if",
  "derive_more",
@@ -465,9 +461,9 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.6.1"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08b108ad2665fa3f6e6a517c3d80ec3e77d224c47d605167aefaa5d7ef97fa48"
+checksum = "678c5130a507ae3a7c797f9a17393c14849300b8440eac47cdb90a5bdcb3a543"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -494,9 +490,9 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.3.0"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79b8558f5a0581152dc94dcd289132a1d377494bdeafcd41869b3258e3e2ad92"
+checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34"
 dependencies = [
  "async-trait",
  "bytes",
@@ -565,6 +561,12 @@ version = "0.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
 
+[[package]]
+name = "base64"
+version = "0.21.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+
 [[package]]
 name = "base64ct"
 version = "1.5.3"
@@ -577,7 +579,7 @@ version = "0.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641"
 dependencies = [
- "base64",
+ "base64 0.13.1",
  "blowfish",
  "getrandom",
  "zeroize",
@@ -589,18 +591,6 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
-[[package]]
-name = "bitvec"
-version = "0.19.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55f93d0ef3363c364d5976646a38f04cf67cfe1d4c8d160cdea02cab2c116b33"
-dependencies = [
- "funty",
- "radium",
- "tap",
- "wyz",
-]
-
 [[package]]
 name = "block-buffer"
 version = "0.10.3"
@@ -633,9 +623,9 @@ dependencies = [
 
 [[package]]
 name = "brotli-decompressor"
-version = "2.3.2"
+version = "2.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59ad2d4653bf5ca36ae797b1f4bb4dbddb60ce49ca4aed8a2ce4829f60425b80"
+checksum = "4b6561fd3f895a11e8f72af2cb7d22e08366bebc2b6b57f7744c4bda27034744"
 dependencies = [
  "alloc-no-stdlib",
  "alloc-stdlib",
@@ -643,9 +633,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.11.1"
+version = "3.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "572f695136211188308f16ad2ca5c851a712c464060ae6974944458eb83880ba"
+checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
 
 [[package]]
 name = "bytecount"
@@ -708,9 +698,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.0.32"
+version = "4.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7db700bc935f9e43e88d00b0850dae18a63773cfbec6d8e070fccf7fef89a39"
+checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2"
 dependencies = [
  "bitflags",
  "clap_derive",
@@ -723,9 +713,9 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.0.21"
+version = "4.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0177313f9f02afc995627906bbd8967e2be069f5261954222dac78290c2b9014"
+checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
 dependencies = [
  "heck",
  "proc-macro-error",
@@ -736,9 +726,9 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d4198f73e42b4936b35b5bb248d81d2b595ecb170da0bac7655c54eedfa8da8"
+checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
 dependencies = [
  "os_str_bytes",
 ]
@@ -752,7 +742,7 @@ dependencies = [
  "async-trait",
  "json5",
  "lazy_static",
- "nom 7.1.2",
+ "nom",
  "pathdiff",
  "ron",
  "rust-ini",
@@ -872,13 +862,13 @@ dependencies = [
 
 [[package]]
 name = "css-minify"
-version = "0.2.2"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "692b185e3b7c9af96b3195f3021f53a931d896968ed2ad3fb1cdb6558b30c9ab"
+checksum = "874c6e2d19f8d4a285083b11a3241bfbe01ac3ed85f26e1e6b34888d960552bd"
 dependencies = [
  "derive_more",
  "indexmap",
- "nom 6.1.2",
+ "nom",
 ]
 
 [[package]]
@@ -926,7 +916,7 @@ dependencies = [
  "hashbrown 0.12.3",
  "lock_api",
  "once_cell",
- "parking_lot_core 0.9.5",
+ "parking_lot_core 0.9.6",
 ]
 
 [[package]]
@@ -1093,12 +1083,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "funty"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fed34cd105917e91daa4da6b3728c47b068749d6a62c59811f06ed2ac71d9da7"
-
 [[package]]
 name = "futf"
 version = "0.1.5"
@@ -1258,9 +1242,9 @@ dependencies = [
 
 [[package]]
 name = "hashbrown"
-version = "0.13.1"
+version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038"
+checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
 dependencies = [
  "ahash 0.8.2",
 ]
@@ -1271,10 +1255,10 @@ version = "7.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8"
 dependencies = [
- "base64",
+ "base64 0.13.1",
  "byteorder",
  "flate2",
- "nom 7.1.2",
+ "nom",
  "num-traits",
 ]
 
@@ -1354,7 +1338,7 @@ dependencies = [
  "actix-rt",
  "actix-web",
  "awc",
- "base64",
+ "base64 0.13.1",
  "futures-util",
  "http-signature-normalization",
  "sha2",
@@ -1478,9 +1462,9 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.3"
+version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46112a93252b123d31a119a8d1a1ac19deac4fac6e0e8b0df58f0d4e5870e63c"
+checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
 dependencies = [
  "libc",
  "windows-sys",
@@ -1488,9 +1472,9 @@ dependencies = [
 
 [[package]]
 name = "ipnet"
-version = "2.7.0"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "11b0d96e660696543b251e58030cf9787df56da39dab19ad60eae7353040917e"
+checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
 
 [[package]]
 name = "iri-string"
@@ -1573,19 +1557,6 @@ dependencies = [
  "spin",
 ]
 
-[[package]]
-name = "lexical-core"
-version = "0.7.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe"
-dependencies = [
- "arrayvec",
- "bitflags",
- "cfg-if",
- "ryu",
- "static_assertions",
-]
-
 [[package]]
 name = "libc"
 version = "0.2.139"
@@ -1653,7 +1624,7 @@ version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "71e7d46de488603ffdd5f30afbc64fbba2378214a2c3a2fb83abf3d33126df17"
 dependencies = [
- "hashbrown 0.13.1",
+ "hashbrown 0.13.2",
 ]
 
 [[package]]
@@ -1806,22 +1777,23 @@ dependencies = [
 
 [[package]]
 name = "minify-html"
-version = "0.10.3"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58f84854d62363972a73c3d8331b85a479366a0871a83f2a01ac11b9ba787c10"
+checksum = "5d2d0e6da317b10501ed44ebe2aa59c3926890a6dd2a0a77d069e5e9ea69b5c0"
 dependencies = [
  "aho-corasick",
  "css-minify",
  "lazy_static",
  "memchr",
  "minify-js",
+ "rustc-hash",
 ]
 
 [[package]]
 name = "minify-js"
-version = "0.2.9"
+version = "0.4.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe033709f5a1159736cf7e22748518ffb75af26f3a6264d52ecc8bb38c68c36"
+checksum = "58a1566cb31504e32f009f6c47ad83f7eeb91d00e8e9845314f1d0b2202ef595"
 dependencies = [
  "lazy_static",
  "parse-js",
@@ -1883,38 +1855,14 @@ dependencies = [
 
 [[package]]
 name = "nom"
-version = "6.1.2"
+version = "7.1.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
-dependencies = [
- "bitvec",
- "funty",
- "lexical-core",
- "memchr",
- "version_check",
-]
-
-[[package]]
-name = "nom"
-version = "7.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5507769c4919c998e69e49c839d9dc6e693ede4cc4290d6ad8b41d4f09c548c"
+checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
 dependencies = [
  "memchr",
  "minimal-lexical",
 ]
 
-[[package]]
-name = "nom_locate"
-version = "4.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37794436ca3029a3089e0b95d42da1f0b565ad271e4d3bb4bad0c7bb70b10605"
-dependencies = [
- "bytecount",
- "memchr",
- "nom 7.1.2",
-]
-
 [[package]]
 name = "nu-ansi-term"
 version = "0.46.0"
@@ -1982,6 +1930,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
 dependencies = [
  "autocfg",
+ "num-bigint",
  "num-integer",
  "num-traits",
 ]
@@ -2141,7 +2090,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.5",
+ "parking_lot_core 0.9.6",
 ]
 
 [[package]]
@@ -2160,9 +2109,9 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.5"
+version = "0.9.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ff9f3fef3968a3ec5945535ed654cb38ff72d7495a25619e2247fb15a2ed9ba"
+checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
 dependencies = [
  "cfg-if",
  "libc",
@@ -2173,9 +2122,9 @@ dependencies = [
 
 [[package]]
 name = "parse-js"
-version = "0.3.1"
+version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "66bb85ec60d22b9e6d4adac1e3dbdaf3903a4485f476c5f4dd7ed1285cbf4dad"
+checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5"
 dependencies = [
  "aho-corasick",
  "lazy_static",
@@ -2211,9 +2160,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.5.2"
+version = "2.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f6e86fb9e7026527a0d46bc308b841d73170ef8f443e1807f6ef88526a816d4"
+checksum = "4257b4a04d91f7e9e6290be5d3da4804dd5784fafde3a497d73eb2b4a158c30a"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2221,9 +2170,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.2"
+version = "2.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "96504449aa860c8dcde14f9fba5c58dc6658688ca1fe363589d6327b8662c603"
+checksum = "241cda393b0cdd65e62e07e12454f1f25d57017dcc514b1514cd3c4645e3a0a6"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2231,9 +2180,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.2"
+version = "2.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "798e0220d1111ae63d66cb66a5dcb3fc2d986d520b98e49e1852bfdb11d7c5e7"
+checksum = "46b53634d8c8196302953c74d5352f33d0c512a9499bd2ce468fc9f4128fa27c"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2244,13 +2193,13 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.5.2"
+version = "2.5.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "984298b75898e30a843e278a9f2452c31e349a073a0ce6fd950a12a74464e065"
+checksum = "0ef4f1332a8d4678b41966bb4cc1d0676880e84183a1ecc3f4b69f03e99c7a51"
 dependencies = [
  "once_cell",
  "pest",
- "sha1",
+ "sha2",
 ]
 
 [[package]]
@@ -2375,9 +2324,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "prettyplease"
-version = "0.1.22"
+version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c8992a85d8e93a28bdf76137db888d3874e3b230dee5ed8bebac4c9f7617773"
+checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78"
 dependencies = [
  "proc-macro2",
  "syn",
@@ -2409,18 +2358,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.49"
+version = "1.0.50"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a8eca9f9c4ffde41714334dee777596264c7825420f521abc92b5b5deb63a5"
+checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.11.5"
+version = "0.11.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c01db6702aa05baa3f57dec92b8eeeeb4cb19e894e73996b32a4093289e54592"
+checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698"
 dependencies = [
  "bytes",
  "prost-derive",
@@ -2428,9 +2377,9 @@ dependencies = [
 
 [[package]]
 name = "prost-build"
-version = "0.11.5"
+version = "0.11.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cb5320c680de74ba083512704acb90fe00f28f79207286a848e730c45dd73ed6"
+checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e"
 dependencies = [
  "bytes",
  "heck",
@@ -2450,9 +2399,9 @@ dependencies = [
 
 [[package]]
 name = "prost-derive"
-version = "0.11.5"
+version = "0.11.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8842bad1a5419bca14eac663ba798f6bc19c413c2fdceb5f3ba3b0932d96720"
+checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
@@ -2463,9 +2412,9 @@ dependencies = [
 
 [[package]]
 name = "prost-types"
-version = "0.11.5"
+version = "0.11.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "017f79637768cde62820bc2d4fe0e45daaa027755c323ad077767c6c5f173091"
+checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788"
 dependencies = [
  "bytes",
  "prost",
@@ -2496,12 +2445,6 @@ dependencies = [
  "proc-macro2",
 ]
 
-[[package]]
-name = "radium"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "941ba9d78d8e2f7ce474c015eea4d9c6d25b6a3327f9832ee29a4de27f91bbb8"
-
 [[package]]
 name = "radix_trie"
 version = "0.2.1"
@@ -2571,9 +2514,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.7.0"
+version = "1.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e076559ef8e241f2ae3479e36f97bd5741c0330689e217ad51ce2c76808b868a"
+checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -2606,11 +2549,11 @@ dependencies = [
 
 [[package]]
 name = "reqwest"
-version = "0.11.13"
+version = "0.11.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68cc60575865c7831548863cc02356512e3f1dc2f3f82cb837d7fc4cc8f3c97c"
+checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9"
 dependencies = [
- "base64",
+ "base64 0.21.0",
  "bytes",
  "encoding_rs",
  "futures-core",
@@ -2640,6 +2583,7 @@ dependencies = [
  "url",
  "wasm-bindgen",
  "wasm-bindgen-futures",
+ "wasm-streams",
  "web-sys",
  "webpki-roots",
  "winreg",
@@ -2666,7 +2610,7 @@ version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
 dependencies = [
- "base64",
+ "base64 0.13.1",
  "bitflags",
  "serde",
 ]
@@ -2698,7 +2642,7 @@ version = "0.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8dc035c92400b90ee471e0ea7e041bfadd4da26dd3e716a84053d0075ed9c159"
 dependencies = [
- "base64",
+ "base64 0.13.1",
  "num-bigint-dig",
  "rsa",
  "thiserror",
@@ -2706,15 +2650,14 @@ dependencies = [
 
 [[package]]
 name = "rsass"
-version = "0.26.0"
+version = "0.27.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "665387d3be91521de331a04cc7118c8c129ffe43c5f4e8a61e78990850046b5a"
+checksum = "a43695dd28122f6c684273de89796a56a98e02e9694b8ab57b160fdc6e6d69af"
 dependencies = [
  "arc-swap",
  "fastrand",
  "lazy_static",
- "nom 7.1.2",
- "nom_locate",
+ "nom",
  "num-bigint",
  "num-integer",
  "num-rational",
@@ -2724,16 +2667,16 @@ dependencies = [
 
 [[package]]
 name = "ructe"
-version = "0.15.0"
+version = "0.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85517cd381cf0c34694881d8aaf173107c6af7670e66cec18d7a1a8bfce3b758"
+checksum = "3a08274953d9f290e34cf6e0335d784b76248dadff96381f94ab42e91e487555"
 dependencies = [
- "base64",
+ "base64 0.21.0",
  "bytecount",
  "itertools 0.10.5",
  "md5",
  "mime",
- "nom 7.1.2",
+ "nom",
  "rsass",
 ]
 
@@ -2747,6 +2690,12 @@ dependencies = [
  "ordered-multimap",
 ]
 
+[[package]]
+name = "rustc-hash"
+version = "1.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
+
 [[package]]
 name = "rustc_version"
 version = "0.4.0"
@@ -2758,9 +2707,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.6"
+version = "0.36.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4feacf7db682c6c329c4ede12649cd36ecab0f3be5b7d74e6a20304725db4549"
+checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
 dependencies = [
  "bitflags",
  "errno",
@@ -2772,9 +2721,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.20.7"
+version = "0.20.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "539a2bfe908f471bfa933876bd1eb6a19cf2176d375f82ef7f99530a40e48c2c"
+checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f"
 dependencies = [
  "log",
  "ring",
@@ -2784,11 +2733,11 @@ dependencies = [
 
 [[package]]
 name = "rustls-pemfile"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55"
+checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
 dependencies = [
- "base64",
+ "base64 0.21.0",
 ]
 
 [[package]]
@@ -2999,12 +2948,6 @@ dependencies = [
  "der",
 ]
 
-[[package]]
-name = "static_assertions"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
-
 [[package]]
 name = "string_cache"
 version = "0.8.4"
@@ -3072,12 +3015,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e"
 
-[[package]]
-name = "tap"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
-
 [[package]]
 name = "teloxide"
 version = "0.11.3"
@@ -3137,9 +3074,9 @@ dependencies = [
 
 [[package]]
 name = "teloxide-macros"
-version = "0.7.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "40a5fc46d9004706ee23e3b73a0f53518f28498f7297813fa9a505a29638ffd6"
+checksum = "0f1d653b093dba5e44cada57a516f572167df37b8a619443e59c8c517bb6d804"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -3174,9 +3111,9 @@ dependencies = [
 
 [[package]]
 name = "termcolor"
-version = "1.1.3"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
 dependencies = [
  "winapi-util",
 ]
@@ -3254,9 +3191,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
 
 [[package]]
 name = "tokio"
-version = "1.23.0"
+version = "1.24.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eab6d665857cc6ca78d6e80303a02cea7a7851e85dfbd77cbdc09bd129f1ef46"
+checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3331,9 +3268,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.5.10"
+version = "0.5.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1333c76748e868a4d9d1017b5ab53171dfd095f70c712fdb4653a406547f598f"
+checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
 dependencies = [
  "serde",
 ]
@@ -3347,7 +3284,7 @@ dependencies = [
  "async-stream",
  "async-trait",
  "axum",
- "base64",
+ "base64 0.13.1",
  "bytes",
  "futures-core",
  "futures-util",
@@ -3449,9 +3386,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d16c2a0c52b267d46ea9a46012a28b3513ce166c28eaeaa875829ed2f8debd19"
+checksum = "4082e4d81173e0b7ad3cfb71e9eaef0dd0cbb7b139fdb56394f488a3b0760b23"
 dependencies = [
  "actix-web",
  "pin-project",
@@ -3560,9 +3497,9 @@ dependencies = [
 
 [[package]]
 name = "try-lock"
-version = "0.2.3"
+version = "0.2.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642"
+checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
 
 [[package]]
 name = "typenum"
@@ -3587,9 +3524,9 @@ dependencies = [
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.8"
+version = "0.3.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
+checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
 
 [[package]]
 name = "unicode-ident"
@@ -3740,6 +3677,19 @@ version = "0.2.83"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
 
+[[package]]
+name = "wasm-streams"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bbae3363c08332cadccd13b67db371814cd214c2524020932f0804b8cf7c078"
+dependencies = [
+ "futures-util",
+ "js-sys",
+ "wasm-bindgen",
+ "wasm-bindgen-futures",
+ "web-sys",
+]
+
 [[package]]
 name = "web-sys"
 version = "0.3.60"
@@ -3771,9 +3721,9 @@ dependencies = [
 
 [[package]]
 name = "which"
-version = "4.3.0"
+version = "4.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b"
+checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
 dependencies = [
  "either",
  "libc",
@@ -3828,45 +3778,45 @@ dependencies = [
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41d2aa71f6f0cbe00ae5167d90ef3cfe66527d6f613ca78ac8024c3ccab9a19e"
+checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd0f252f5a35cac83d6311b2e795981f5ee6e67eb1f9a7f64eb4500fbc4dcdb4"
+checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbeae19f6716841636c28d695375df17562ca208b2b7d0dc47635a50ae6c5de7"
+checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84c12f65daa39dd2babe6e442988fc329d6243fdce47d7d2d155b8d874862246"
+checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf7b1b21b5362cbc318f686150e5bcea75ecedc74dd157d874d754a2ca44b0ed"
+checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09d525d2ba30eeb3297665bd434a54297e4170c7f1a44cad4ef58095b4cd2028"
+checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.42.0"
+version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f40009d85759725a34da6d89a94e63d7bdc50a862acf0dbc7c8e488f1edcb6f5"
+checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
 
 [[package]]
 name = "winreg"
@@ -3877,12 +3827,6 @@ dependencies = [
  "winapi",
 ]
 
-[[package]]
-name = "wyz"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85e60b0d1b5f99db2556934e21937020776a5d31520bf169e851ac44e6420214"
-
 [[package]]
 name = "yaml-rust"
 version = "0.4.5"
diff --git a/Cargo.toml b/Cargo.toml
index e61fa5f..70eae4e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -34,7 +34,7 @@ activitystreams-ext = "0.1.0-alpha.3"
 ammonia = "3.1.0"
 awc = { version = "3.0.0", default-features = false, features = ["rustls"] }
 bcrypt = "0.13"
-base64 = "0.13"
+base64 = "0.21"
 clap = { version = "4.0.0", features = ["derive"] }
 config = "0.13.0"
 console-subscriber = { version = "0.1", optional = true }
@@ -100,7 +100,7 @@ version = "0.7.0"
 [build-dependencies]
 anyhow = "1.0"
 dotenv = "0.15.0"
-ructe = { version = "0.15.0", features = ["sass", "mime03"] }
+ructe = { version = "0.16.0", features = ["sass", "mime03"] }
 toml = "0.5.8"
 
 [profile.dev.package.rsa]
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index a982563..3bc3eaa 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -6,6 +6,7 @@ use crate::{
 };
 use activitystreams::{base::BaseExt, iri, iri_string::types::IriString};
 use actix_web::web;
+use base64::{engine::general_purpose::STANDARD, Engine};
 use http_signature_normalization_actix::{prelude::*, verify::DeprecatedAlgorithm};
 use rsa::{pkcs1v15::VerifyingKey, pkcs8::DecodePublicKey, RsaPublicKey};
 use sha2::{Digest, Sha256};
@@ -127,7 +128,7 @@ async fn do_verify(
     let span = tracing::Span::current();
     web::block(move || {
         span.in_scope(|| {
-            let decoded = base64::decode(signature)?;
+            let decoded = STANDARD.decode(signature)?;
             let signature = Signature::from_bytes(&decoded).map_err(ErrorKind::ReadSignature)?;
             let hashed = Sha256::new_with_prefix(signing_string.as_bytes());
 
diff --git a/src/requests.rs b/src/requests.rs
index 9a1bc50..121b566 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -5,6 +5,7 @@ use crate::{
 use activitystreams::iri_string::types::IriString;
 use actix_web::http::header::Date;
 use awc::{error::SendRequestError, Client, ClientResponse};
+use base64::{engine::general_purpose::STANDARD, Engine};
 use dashmap::DashMap;
 use http_signature_normalization_actix::prelude::*;
 use rand::thread_rng;
@@ -391,6 +392,6 @@ impl Signer {
     fn sign(&self, signing_string: &str) -> Result<String, Error> {
         let signing_key = SigningKey::<Sha256>::new_with_prefix(self.private_key.clone());
         let signature = signing_key.try_sign_with_rng(thread_rng(), signing_string.as_bytes())?;
-        Ok(base64::encode(signature.as_ref()))
+        Ok(STANDARD.encode(signature.as_ref()))
     }
 }
diff --git a/src/routes/index.rs b/src/routes/index.rs
index 835e2b8..d1b4b21 100644
--- a/src/routes/index.rs
+++ b/src/routes/index.rs
@@ -71,7 +71,7 @@ pub(crate) async fn route(
 
     let mut buf = BufWriter::new(Vec::new());
 
-    crate::templates::index(&mut buf, &local, &nodes, &config)?;
+    crate::templates::index_html(&mut buf, &local, &nodes, &config)?;
     let html = buf.into_inner().map_err(|e| {
         tracing::error!("Error rendering template, {}", e.error());
         ErrorKind::FlushBuffer
diff --git a/templates/index.rs.html b/templates/index.rs.html
index b7c39f6..f6bd35c 100644
--- a/templates/index.rs.html
+++ b/templates/index.rs.html
@@ -1,7 +1,7 @@
 @use crate::{
 config::{Config, UrlKind},
 data::Node,
-templates::{info, instance, statics::index_css},
+templates::{info_html, instance_html, statics::index_css},
 };
 
 @(local: &[Node], nodes: &[Node], config: &Config)
@@ -39,13 +39,13 @@ templates::{info, instance, statics::index_css},
         @for node in local {
         @if let Some(inst) = node.instance.as_ref() {
         <li>
-          @:instance(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(),
+          @:instance_html(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(),
           &node.base)
         </li>
         } else {
         @if let Some(inf) = node.info.as_ref() {
         <li>
-          @:info(inf, &node.base)
+          @:info_html(inf, &node.base)
         </li>
         }
         }
@@ -97,13 +97,13 @@ templates::{info, instance, statics::index_css},
         @for node in nodes {
         @if let Some(inst) = node.instance.as_ref() {
         <li>
-          @:instance(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(),
+          @:instance_html(inst, node.info.as_ref().map(|info| { info.software.as_ref() }), node.contact.as_ref(),
           &node.base)
         </li>
         } else {
         @if let Some(inf) = node.info.as_ref() {
         <li>
-          @:info(inf, &node.base)
+          @:info_html(inf, &node.base)
         </li>
         }
         }
diff --git a/templates/instance.rs.html b/templates/instance.rs.html
index e36cffa..96adb94 100644
--- a/templates/instance.rs.html
+++ b/templates/instance.rs.html
@@ -1,4 +1,4 @@
-@use crate::{db::{Contact, Instance}, templates::admin};
+@use crate::{db::{Contact, Instance}, templates::admin_html};
 @use activitystreams::iri_string::types::IriString;
 
 @(instance: &Instance, software: Option<&str>, contact: Option<&Contact>, base: &IriString)
@@ -30,7 +30,7 @@
         }
         @if let Some(contact) = contact {
         <h5 class="instance-admin">@instance.title's admin:</h5>
-        @:admin(contact, base)
+        @:admin_html(contact, base)
         }
       </div>
       }

From 34dc1a22814150d84ce7b5593d2c57b62bc6334a Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 23 Jan 2023 08:56:18 -0600
Subject: [PATCH 56/87] Update rsa

---
 Cargo.lock                 | 18 ++++++++----------
 Cargo.toml                 |  6 ++----
 src/config.rs              |  2 +-
 src/error.rs               |  6 +++---
 src/middleware/verifier.rs | 15 ++++++++-------
 src/requests.rs            | 12 ++++++++----
 6 files changed, 30 insertions(+), 29 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 68428c3..0ff61c8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -349,8 +349,6 @@ dependencies = [
  "rustls-pemfile",
  "serde",
  "serde_json",
- "sha2",
- "signature",
  "sled",
  "teloxide",
  "thiserror",
@@ -2617,9 +2615,9 @@ dependencies = [
 
 [[package]]
 name = "rsa"
-version = "0.7.2"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c"
+checksum = "89b3896c9b7790b70a9aa314a30e4ae114200992a19c96cbe0ca6070edd32ab8"
 dependencies = [
  "byteorder",
  "digest",
@@ -2630,19 +2628,19 @@ dependencies = [
  "pkcs1",
  "pkcs8",
  "rand_core",
+ "sha2",
  "signature",
- "smallvec",
  "subtle",
  "zeroize",
 ]
 
 [[package]]
 name = "rsa-magic-public-key"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8dc035c92400b90ee471e0ea7e041bfadd4da26dd3e716a84053d0075ed9c159"
+checksum = "a86cb93425d6e176cfa39d63e226289f13154173f18274fab609c71ff35ba3a0"
 dependencies = [
- "base64 0.13.1",
+ "base64 0.21.0",
  "num-bigint-dig",
  "rsa",
  "thiserror",
@@ -2871,9 +2869,9 @@ dependencies = [
 
 [[package]]
 name = "signature"
-version = "1.6.4"
+version = "2.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d"
 dependencies = [
  "digest",
  "rand_core",
diff --git a/Cargo.toml b/Cargo.toml
index 70eae4e..5d57dd0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -54,14 +54,12 @@ opentelemetry-otlp = "0.11"
 pin-project-lite = "0.2.9"
 quanta = "0.10.1"
 rand = "0.8"
-rsa = "0.7"
-rsa-magic-public-key = "0.6.0"
+rsa = { version = "0.8", features = ["sha2"] }
+rsa-magic-public-key = "0.7.0"
 rustls = "0.20.7"
 rustls-pemfile = "1.0.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
-sha2 = { version = "0.10", features = ["oid"] }
-signature = "1.6.4"
 sled = "0.34.7"
 teloxide = { version = "0.11.1", default-features = false, features = [
   "ctrlc_handler",
diff --git a/src/config.rs b/src/config.rs
index 848cc5b..78caaf5 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -12,8 +12,8 @@ use activitystreams::{
 };
 use config::Environment;
 use http_signature_normalization_actix::prelude::VerifyDigest;
+use rsa::sha2::{Digest, Sha256};
 use rustls::{Certificate, PrivateKey};
-use sha2::{Digest, Sha256};
 use std::{
     io::BufReader,
     net::{IpAddr, SocketAddr},
diff --git a/src/error.rs b/src/error.rs
index 2f9e658..4818e3f 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -99,13 +99,13 @@ pub(crate) enum ErrorKind {
     PrepareSign(#[from] PrepareSignError),
 
     #[error("Couldn't sign digest")]
-    Signature(#[from] signature::Error),
+    Signature(#[from] rsa::signature::Error),
 
     #[error("Couldn't read signature")]
-    ReadSignature(signature::Error),
+    ReadSignature(rsa::signature::Error),
 
     #[error("Couldn't verify signature")]
-    VerifySignature(signature::Error),
+    VerifySignature(rsa::signature::Error),
 
     #[error("Couldn't parse the signature header")]
     HeaderValidation(#[from] actix_web::http::header::InvalidHeaderValue),
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index 3bc3eaa..e9aa321 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -8,9 +8,10 @@ use activitystreams::{base::BaseExt, iri, iri_string::types::IriString};
 use actix_web::web;
 use base64::{engine::general_purpose::STANDARD, Engine};
 use http_signature_normalization_actix::{prelude::*, verify::DeprecatedAlgorithm};
-use rsa::{pkcs1v15::VerifyingKey, pkcs8::DecodePublicKey, RsaPublicKey};
-use sha2::{Digest, Sha256};
-use signature::{DigestVerifier, Signature};
+use rsa::{
+    pkcs1v15::Signature, pkcs1v15::VerifyingKey, pkcs8::DecodePublicKey, sha2::Sha256,
+    signature::Verifier, RsaPublicKey,
+};
 use std::{future::Future, pin::Pin};
 
 #[derive(Clone, Debug)]
@@ -129,12 +130,12 @@ async fn do_verify(
     web::block(move || {
         span.in_scope(|| {
             let decoded = STANDARD.decode(signature)?;
-            let signature = Signature::from_bytes(&decoded).map_err(ErrorKind::ReadSignature)?;
-            let hashed = Sha256::new_with_prefix(signing_string.as_bytes());
+            let signature =
+                Signature::try_from(decoded.as_slice()).map_err(ErrorKind::ReadSignature)?;
 
-            let verifying_key = VerifyingKey::new_with_prefix(public_key);
+            let verifying_key = VerifyingKey::<Sha256>::new_with_prefix(public_key);
             verifying_key
-                .verify_digest(hashed, &signature)
+                .verify(signing_string.as_bytes(), &signature)
                 .map_err(ErrorKind::VerifySignature)?;
 
             Ok(()) as Result<(), Error>
diff --git a/src/requests.rs b/src/requests.rs
index 121b566..d948a22 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -9,9 +9,12 @@ use base64::{engine::general_purpose::STANDARD, Engine};
 use dashmap::DashMap;
 use http_signature_normalization_actix::prelude::*;
 use rand::thread_rng;
-use rsa::{pkcs1v15::SigningKey, RsaPrivateKey};
-use sha2::{Digest, Sha256};
-use signature::RandomizedSigner;
+use rsa::{
+    pkcs1v15::SigningKey,
+    sha2::{Digest, Sha256},
+    signature::RandomizedSigner,
+    RsaPrivateKey,
+};
 use std::{
     cell::RefCell,
     rc::Rc,
@@ -391,7 +394,8 @@ struct Signer {
 impl Signer {
     fn sign(&self, signing_string: &str) -> Result<String, Error> {
         let signing_key = SigningKey::<Sha256>::new_with_prefix(self.private_key.clone());
-        let signature = signing_key.try_sign_with_rng(thread_rng(), signing_string.as_bytes())?;
+        let signature =
+            signing_key.try_sign_with_rng(&mut thread_rng(), signing_string.as_bytes())?;
         Ok(STANDARD.encode(signature.as_ref()))
     }
 }

From e93dd2da5651e82fc9b4b43ca16fa7a69c6ebfdd Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 23 Jan 2023 08:57:16 -0600
Subject: [PATCH 57/87] Update teloxide

---
 Cargo.lock | 8 ++++----
 Cargo.toml | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0ff61c8..1ba2fb5 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3015,9 +3015,9 @@ checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e"
 
 [[package]]
 name = "teloxide"
-version = "0.11.3"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59c3b28292b33a57a8d71ce000c23fdaffeb0b4aec35fa9351d4be7ec6376a3f"
+checksum = "c0b08789da4f24d049aea06e17c1c7b92c1b92222115e357014a46e842fb8c84"
 dependencies = [
  "aquamarine",
  "bytes",
@@ -3041,9 +3041,9 @@ dependencies = [
 
 [[package]]
 name = "teloxide-core"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9243a720aa9bddda324a7f90b4ab42887425524bf4d5d24a56b50bccb984b7c4"
+checksum = "25d05d54e4c83825f143da24f0fe35c1171b634f3ba1f6c9e2fae6d98e2446b6"
 dependencies = [
  "bitflags",
  "bytes",
diff --git a/Cargo.toml b/Cargo.toml
index 5d57dd0..8533aa9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -61,7 +61,7 @@ rustls-pemfile = "1.0.1"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 sled = "0.34.7"
-teloxide = { version = "0.11.1", default-features = false, features = [
+teloxide = { version = "0.12.0", default-features = false, features = [
   "ctrlc_handler",
   "macros",
   "rustls",

From c11ff171920b2c834f9c154b111ed40d0c899f32 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Mon, 23 Jan 2023 08:58:07 -0600
Subject: [PATCH 58/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 1ba2fb5..df71567 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.79"
+version = "0.3.80"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 8533aa9..c78fad1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.79"
+version = "0.3.80"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From 96547230bc2b45f6897da587a0f67cf86440ebb6 Mon Sep 17 00:00:00 2001
From: Tealk <tealk@rollenspiel.monster>
Date: Sat, 28 Jan 2023 23:45:31 +0100
Subject: [PATCH 59/87] update Pleroma text

Signed-off-by: Tealk <tealk@rollenspiel.monster>
---
 templates/index.rs.html | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/templates/index.rs.html b/templates/index.rs.html
index f6bd35c..19e8acf 100644
--- a/templates/index.rs.html
+++ b/templates/index.rs.html
@@ -79,9 +79,7 @@ templates::{info_html, instance_html, statics::index_css},
         <h4>Pleroma</h4>
         <p>
           Pleroma admins can add this relay by adding
-        <pre>@config.generate_url(UrlKind::Actor)</pre>
-        to their relay settings (I don't actually know how pleroma handles adding
-        relays, is it still a mix command?).
+        <pre>@config.generate_url(UrlKind::Actor)</pre> to their relay settings.
         </p>
         <h4>Others</h4>
         <p>

From f9cad61049614b7d102eb888786ba27c672df4d7 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 29 Jan 2023 13:21:36 -0600
Subject: [PATCH 60/87] Add healthcheck for db, new clippy lints

---
 src/build.rs               |  8 ++++----
 src/collector/stats.rs     | 32 ++++++++++++++++----------------
 src/config.rs              | 14 +++++++-------
 src/data/node.rs           |  2 +-
 src/db.rs                  | 30 ++++++++++++++++++++++++++----
 src/jobs/instance.rs       |  2 +-
 src/jobs/nodeinfo.rs       |  6 +++---
 src/main.rs                |  3 ++-
 src/middleware/verifier.rs |  6 +++---
 src/requests.rs            |  4 ++--
 src/routes.rs              |  2 ++
 src/routes/healthz.rs      |  7 +++++++
 src/telegram.rs            |  8 ++++----
 13 files changed, 78 insertions(+), 46 deletions(-)
 create mode 100644 src/routes/healthz.rs

diff --git a/src/build.rs b/src/build.rs
index ebac904..f21d5bb 100644
--- a/src/build.rs
+++ b/src/build.rs
@@ -5,7 +5,7 @@ fn git_info() {
     if let Ok(output) = Command::new("git").args(["rev-parse", "HEAD"]).output() {
         if output.status.success() {
             let git_hash = String::from_utf8_lossy(&output.stdout);
-            println!("cargo:rustc-env=GIT_HASH={}", git_hash);
+            println!("cargo:rustc-env=GIT_HASH={git_hash}");
             println!("cargo:rustc-env=GIT_SHORT_HASH={}", &git_hash[..8])
         }
     }
@@ -16,7 +16,7 @@ fn git_info() {
     {
         if output.status.success() {
             let git_branch = String::from_utf8_lossy(&output.stdout);
-            println!("cargo:rustc-env=GIT_BRANCH={}", git_branch);
+            println!("cargo:rustc-env=GIT_BRANCH={git_branch}");
         }
     }
 }
@@ -32,11 +32,11 @@ fn version_info() -> Result<(), anyhow::Error> {
     let data: toml::Value = toml::from_str(&cargo_data)?;
 
     if let Some(version) = data["package"]["version"].as_str() {
-        println!("cargo:rustc-env=PKG_VERSION={}", version);
+        println!("cargo:rustc-env=PKG_VERSION={version}");
     }
 
     if let Some(name) = data["package"]["name"].as_str() {
-        println!("cargo:rustc-env=PKG_NAME={}", name);
+        println!("cargo:rustc-env=PKG_NAME={name}");
     }
 
     Ok(())
diff --git a/src/collector/stats.rs b/src/collector/stats.rs
index c8d1812..91f235f 100644
--- a/src/collector/stats.rs
+++ b/src/collector/stats.rs
@@ -40,11 +40,11 @@ impl std::fmt::Display for Counter {
         let labels = self
             .labels
             .iter()
-            .map(|(k, v)| format!("{}: {}", k, v))
+            .map(|(k, v)| format!("{k}: {v}"))
             .collect::<Vec<_>>()
             .join(", ");
 
-        write!(f, "{} - {}", labels, self.value)
+        write!(f, "{labels} - {}", self.value)
     }
 }
 
@@ -59,11 +59,11 @@ impl std::fmt::Display for Gauge {
         let labels = self
             .labels
             .iter()
-            .map(|(k, v)| format!("{}: {}", k, v))
+            .map(|(k, v)| format!("{k}: {v}"))
             .collect::<Vec<_>>()
             .join(", ");
 
-        write!(f, "{} - {}", labels, self.value)
+        write!(f, "{labels} - {}", self.value)
     }
 }
 
@@ -78,7 +78,7 @@ impl std::fmt::Display for Histogram {
         let labels = self
             .labels
             .iter()
-            .map(|(k, v)| format!("{}: {}", k, v))
+            .map(|(k, v)| format!("{k}: {v}"))
             .collect::<Vec<_>>()
             .join(", ");
 
@@ -87,15 +87,15 @@ impl std::fmt::Display for Histogram {
             .iter()
             .map(|(k, v)| {
                 if let Some(v) = v {
-                    format!("{}: {:.6}", k, v)
+                    format!("{k}: {v:.6}")
                 } else {
-                    format!("{}: None,", k)
+                    format!("{k}: None,")
                 }
             })
             .collect::<Vec<_>>()
             .join(", ");
 
-        write!(f, "{} - {}", labels, value)
+        write!(f, "{labels} - {value}")
     }
 }
 
@@ -172,18 +172,18 @@ impl Snapshot {
                     continue;
                 }
 
-                println!("\t{}", key);
+                println!("\t{key}");
                 for counter in counters {
-                    println!("\t\t{}", counter);
+                    println!("\t\t{counter}");
                 }
             }
 
             for (key, counters) in merging {
-                println!("\t{}", key);
+                println!("\t{key}");
 
                 for (_, counter) in counters {
                     if let Some(counter) = counter.merge() {
-                        println!("\t\t{}", counter);
+                        println!("\t\t{counter}");
                     }
                 }
             }
@@ -192,10 +192,10 @@ impl Snapshot {
         if !self.gauges.is_empty() {
             println!("Gauges");
             for (key, gauges) in self.gauges {
-                println!("\t{}", key);
+                println!("\t{key}");
 
                 for gauge in gauges {
-                    println!("\t\t{}", gauge);
+                    println!("\t\t{gauge}");
                 }
             }
         }
@@ -203,10 +203,10 @@ impl Snapshot {
         if !self.histograms.is_empty() {
             println!("Histograms");
             for (key, histograms) in self.histograms {
-                println!("\t{}", key);
+                println!("\t{key}");
 
                 for histogram in histograms {
-                    println!("\t\t{}", histogram);
+                    println!("\t\t{histogram}");
                 }
             }
         }
diff --git a/src/config.rs b/src/config.rs
index 78caaf5..db21f9d 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -170,7 +170,7 @@ impl Config {
         let config: ParsedConfig = config.try_deserialize()?;
 
         let scheme = if config.https { "https" } else { "http" };
-        let base_uri = iri!(format!("{}://{}", scheme, config.hostname)).into_absolute();
+        let base_uri = iri!(format!("{scheme}://{}", config.hostname)).into_absolute();
 
         let tls = match (config.tls_key, config.tls_cert) {
             (Some(key), Some(cert)) => Some(TlsConfig { key, cert }),
@@ -207,8 +207,8 @@ impl Config {
 
         let source_url = match Self::git_hash() {
             Some(hash) => format!(
-                "{}{}{}",
-                config.source_repo, config.repository_commit_base, hash
+                "{}{}{hash}",
+                config.source_repo, config.repository_commit_base
             )
             .parse()
             .expect("constructed source URL is valid"),
@@ -332,7 +332,7 @@ impl Config {
             match AdminConfig::build(api_token) {
                 Ok(conf) => Some(actix_web::web::Data::new(conf)),
                 Err(e) => {
-                    tracing::error!("Error creating admin config: {}", e);
+                    tracing::error!("Error creating admin config: {e}");
                     None
                 }
             }
@@ -371,7 +371,7 @@ impl Config {
 
     pub(crate) fn software_version() -> String {
         if let Some(git) = Self::git_version() {
-            return format!("v{}-{}", Self::version(), git);
+            return format!("v{}-{git}", Self::version());
         }
 
         format!("v{}", Self::version())
@@ -381,7 +381,7 @@ impl Config {
         let branch = Self::git_branch()?;
         let hash = Self::git_short_hash()?;
 
-        Some(format!("{}-{}", branch, hash))
+        Some(format!("{branch}-{hash}"))
     }
 
     fn name() -> &'static str {
@@ -463,7 +463,7 @@ impl Config {
                 resolved
             }
             UrlKind::Media(uuid) => FixedBaseResolver::new(self.base_uri.as_ref())
-                .resolve(IriRelativeStr::new(&format!("media/{}", uuid))?.as_ref())
+                .resolve(IriRelativeStr::new(&format!("media/{uuid}"))?.as_ref())
                 .try_to_dedicated_string()?,
             UrlKind::NodeInfo => FixedBaseResolver::new(self.base_uri.as_ref())
                 .resolve(IriRelativeStr::new("nodeinfo/2.0.json")?.as_ref())
diff --git a/src/data/node.rs b/src/data/node.rs
index 4ba6eb5..ac89cdb 100644
--- a/src/data/node.rs
+++ b/src/data/node.rs
@@ -182,7 +182,7 @@ impl Node {
         let authority = url.authority_str().ok_or(ErrorKind::MissingDomain)?;
         let scheme = url.scheme_str();
 
-        let base = iri!(format!("{}://{}", scheme, authority));
+        let base = iri!(format!("{scheme}://{authority}"));
 
         Ok(Node {
             base,
diff --git a/src/db.rs b/src/db.rs
index 6d3064f..6713cba 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -10,7 +10,10 @@ use rsa::{
 use sled::{Batch, Tree};
 use std::{
     collections::{BTreeMap, HashMap},
-    sync::Arc,
+    sync::{
+        atomic::{AtomicU64, Ordering},
+        Arc,
+    },
     time::SystemTime,
 };
 use time::OffsetDateTime;
@@ -22,6 +25,8 @@ pub(crate) struct Db {
 }
 
 struct Inner {
+    healthz: Tree,
+    healthz_counter: Arc<AtomicU64>,
     actor_id_actor: Tree,
     public_key_id_actor_id: Tree,
     connected_actor_ids: Tree,
@@ -242,6 +247,8 @@ impl Db {
     fn build_inner(restricted_mode: bool, db: sled::Db) -> Result<Self, Error> {
         Ok(Db {
             inner: Arc::new(Inner {
+                healthz: db.open_tree("healthz")?,
+                healthz_counter: Arc::new(AtomicU64::new(0)),
                 actor_id_actor: db.open_tree("actor-id-actor")?,
                 public_key_id_actor_id: db.open_tree("public-key-id-actor-id")?,
                 connected_actor_ids: db.open_tree("connected-actor-ids")?,
@@ -273,6 +280,21 @@ impl Db {
         Ok(t)
     }
 
+    pub(crate) async fn check_health(&self) -> Result<(), Error> {
+        let next = self.inner.healthz_counter.fetch_add(1, Ordering::Relaxed);
+        self.unblock(move |inner| {
+            inner
+                .healthz
+                .insert("healthz", &next.to_be_bytes()[..])
+                .map_err(Error::from)
+        })
+        .await?;
+        self.inner.healthz.flush_async().await?;
+        self.unblock(move |inner| inner.healthz.get("healthz").map_err(Error::from))
+            .await?;
+        Ok(())
+    }
+
     pub(crate) async fn mark_last_seen(
         &self,
         nodes: HashMap<String, OffsetDateTime>,
@@ -468,7 +490,7 @@ impl Db {
     pub(crate) async fn is_connected(&self, base_id: IriString) -> Result<bool, Error> {
         let scheme = base_id.scheme_str();
         let authority = base_id.authority_str().ok_or(ErrorKind::MissingDomain)?;
-        let prefix = format!("{}://{}", scheme, authority);
+        let prefix = format!("{scheme}://{authority}");
 
         self.unblock(move |inner| {
             let connected = inner
@@ -528,7 +550,7 @@ impl Db {
     }
 
     pub(crate) async fn remove_connection(&self, actor_id: IriString) -> Result<(), Error> {
-        tracing::debug!("Removing Connection: {}", actor_id);
+        tracing::debug!("Removing Connection: {actor_id}");
         self.unblock(move |inner| {
             inner
                 .connected_actor_ids
@@ -540,7 +562,7 @@ impl Db {
     }
 
     pub(crate) async fn add_connection(&self, actor_id: IriString) -> Result<(), Error> {
-        tracing::debug!("Adding Connection: {}", actor_id);
+        tracing::debug!("Adding Connection: {actor_id}");
         self.unblock(move |inner| {
             inner
                 .connected_actor_ids
diff --git a/src/jobs/instance.rs b/src/jobs/instance.rs
index 2f1e5c7..650c8ce 100644
--- a/src/jobs/instance.rs
+++ b/src/jobs/instance.rs
@@ -45,7 +45,7 @@ impl QueryInstance {
             .authority_str()
             .ok_or(ErrorKind::MissingDomain)?;
         let scheme = self.actor_id.scheme_str();
-        let instance_uri = iri!(format!("{}://{}/api/v1/instance", scheme, authority));
+        let instance_uri = iri!(format!("{scheme}://{authority}/api/v1/instance"));
 
         let instance = match state
             .requests
diff --git a/src/jobs/nodeinfo.rs b/src/jobs/nodeinfo.rs
index fe86ad8..271b5a1 100644
--- a/src/jobs/nodeinfo.rs
+++ b/src/jobs/nodeinfo.rs
@@ -39,7 +39,7 @@ impl QueryNodeinfo {
             .authority_str()
             .ok_or(ErrorKind::MissingDomain)?;
         let scheme = self.actor_id.scheme_str();
-        let well_known_uri = iri!(format!("{}://{}/.well-known/nodeinfo", scheme, authority));
+        let well_known_uri = iri!(format!("{scheme}://{authority}/.well-known/nodeinfo"));
 
         let well_known = match state
             .requests
@@ -168,7 +168,7 @@ impl<'de> serde::de::Visitor<'de> for SupportedVersionVisitor {
     type Value = SupportedVersion;
 
     fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        write!(f, "a string starting with '{}'", SUPPORTED_VERSIONS)
+        write!(f, "a string starting with '{SUPPORTED_VERSIONS}'")
     }
 
     fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
@@ -187,7 +187,7 @@ impl<'de> serde::de::Visitor<'de> for SupportedNodeinfoVisitor {
     type Value = SupportedNodeinfo;
 
     fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
-        write!(f, "a string starting with '{}'", SUPPORTED_NODEINFO)
+        write!(f, "a string starting with '{SUPPORTED_NODEINFO}'")
     }
 
     fn visit_str<E>(self, s: &str) -> Result<Self::Value, E>
diff --git a/src/main.rs b/src/main.rs
index 39bba1d..22764a2 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -39,7 +39,7 @@ use self::{
     db::Db,
     jobs::create_workers,
     middleware::{DebugPayload, MyVerify, RelayResolver, Timings},
-    routes::{actor, inbox, index, nodeinfo, nodeinfo_meta, statics},
+    routes::{actor, healthz, inbox, index, nodeinfo, nodeinfo_meta, statics},
 };
 
 fn init_subscriber(
@@ -273,6 +273,7 @@ async fn do_server_main(
         app.wrap(Compress::default())
             .wrap(TracingLogger::default())
             .wrap(Timings)
+            .route("/healthz", web::get().to(healthz))
             .service(web::resource("/").route(web::get().to(index)))
             .service(web::resource("/media/{path}").route(web::get().to(routes::media)))
             .service(
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index e9aa321..2ae9779 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -75,7 +75,7 @@ impl MyVerify {
                 Ok(res) => res.actor_id().ok_or(ErrorKind::MissingId),
                 Err(e) => {
                     if e.is_gone() {
-                        tracing::warn!("Actor gone: {}", public_key_id);
+                        tracing::warn!("Actor gone: {public_key_id}");
                         return Ok(false);
                     } else {
                         return Err(e);
@@ -178,13 +178,13 @@ mod tests {
 
     #[test]
     fn handles_masto_keys() {
-        println!("{}", ASONIX_DOG_KEY);
+        println!("{ASONIX_DOG_KEY}");
         let _ = RsaPublicKey::from_public_key_pem(ASONIX_DOG_KEY.trim()).unwrap();
     }
 
     #[test]
     fn handles_pleromo_keys() {
-        println!("{}", KARJALAZET_KEY);
+        println!("{KARJALAZET_KEY}");
         let _ = RsaPublicKey::from_public_key_pem(KARJALAZET_KEY.trim()).unwrap();
     }
 
diff --git a/src/requests.rs b/src/requests.rs
index d948a22..18b9840 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -61,7 +61,7 @@ impl Breakers {
                 if let Some(mut breaker) = self.inner.get_mut(authority) {
                     breaker.fail();
                     if !breaker.should_try() {
-                        tracing::warn!("Failed breaker for {}", authority);
+                        tracing::warn!("Failed breaker for {authority}");
                     }
                     false
                 } else {
@@ -235,7 +235,7 @@ impl Requests {
             if let Ok(bytes) = res.body().await {
                 if let Ok(s) = String::from_utf8(bytes.as_ref().to_vec()) {
                     if !s.is_empty() {
-                        tracing::warn!("Response from {}, {}", parsed_url, s);
+                        tracing::warn!("Response from {parsed_url}, {s}");
                     }
                 }
             }
diff --git a/src/routes.rs b/src/routes.rs
index d80a0a1..9afd38b 100644
--- a/src/routes.rs
+++ b/src/routes.rs
@@ -1,4 +1,5 @@
 mod actor;
+mod healthz;
 mod inbox;
 mod index;
 mod media;
@@ -7,6 +8,7 @@ mod statics;
 
 pub(crate) use self::{
     actor::route as actor,
+    healthz::route as healthz,
     inbox::route as inbox,
     index::route as index,
     media::route as media,
diff --git a/src/routes/healthz.rs b/src/routes/healthz.rs
new file mode 100644
index 0000000..f297ba5
--- /dev/null
+++ b/src/routes/healthz.rs
@@ -0,0 +1,7 @@
+use crate::{data::State, error::Error};
+use actix_web::{web, HttpResponse};
+
+pub(crate) async fn route(state: web::Data<State>) -> Result<HttpResponse, Error> {
+    state.db.check_health().await?;
+    Ok(HttpResponse::Ok().finish())
+}
diff --git a/src/telegram.rs b/src/telegram.rs
index 270e1af..f3cce43 100644
--- a/src/telegram.rs
+++ b/src/telegram.rs
@@ -89,19 +89,19 @@ async fn answer(bot: Bot, msg: Message, cmd: Command, db: Db) -> ResponseResult<
                 .await?;
         }
         Command::Block { domain } if db.add_blocks(vec![domain.clone()]).await.is_ok() => {
-            bot.send_message(msg.chat.id, format!("{} has been blocked", domain))
+            bot.send_message(msg.chat.id, format!("{domain} has been blocked"))
                 .await?;
         }
         Command::Unblock { domain } if db.remove_blocks(vec![domain.clone()]).await.is_ok() => {
-            bot.send_message(msg.chat.id, format!("{} has been unblocked", domain))
+            bot.send_message(msg.chat.id, format!("{domain} has been unblocked"))
                 .await?;
         }
         Command::Allow { domain } if db.add_allows(vec![domain.clone()]).await.is_ok() => {
-            bot.send_message(msg.chat.id, format!("{} has been allowed", domain))
+            bot.send_message(msg.chat.id, format!("{domain} has been allowed"))
                 .await?;
         }
         Command::Disallow { domain } if db.remove_allows(vec![domain.clone()]).await.is_ok() => {
-            bot.send_message(msg.chat.id, format!("{} has been disallowed", domain))
+            bot.send_message(msg.chat.id, format!("{domain} has been disallowed"))
                 .await?;
         }
         Command::ListAllowed => {

From 0e9b88a7ae0acfe0038f1890bcc7ba8885b2dad7 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 29 Jan 2023 13:21:53 -0600
Subject: [PATCH 61/87] Bump deps

---
 Cargo.lock | 98 +++++++++++++++++++++++++++++++++++++++++-------------
 Cargo.toml |  2 +-
 2 files changed, 76 insertions(+), 24 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index df71567..cb6e3aa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -257,9 +257,9 @@ dependencies = [
 
 [[package]]
 name = "ahash"
-version = "0.8.2"
+version = "0.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107"
+checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
 dependencies = [
  "cfg-if",
  "once_cell",
@@ -354,7 +354,7 @@ dependencies = [
  "thiserror",
  "time",
  "tokio",
- "toml",
+ "toml 0.7.0",
  "tracing",
  "tracing-actix-web",
  "tracing-awc",
@@ -459,9 +459,9 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.6.3"
+version = "0.6.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "678c5130a507ae3a7c797f9a17393c14849300b8440eac47cdb90a5bdcb3a543"
+checksum = "e5694b64066a2459918d8074c2ce0d5a88f409431994c2356617c8ae0c4721fc"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -664,9 +664,9 @@ dependencies = [
 
 [[package]]
 name = "cc"
-version = "1.0.78"
+version = "1.0.79"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d"
+checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
 
 [[package]]
 name = "cfg-if"
@@ -696,9 +696,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.1.1"
+version = "4.1.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ec7a4128863c188deefe750ac1d1dfe66c236909f845af04beed823638dc1b2"
+checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
 dependencies = [
  "bitflags",
  "clap_derive",
@@ -746,7 +746,7 @@ dependencies = [
  "rust-ini",
  "serde",
  "serde_json",
- "toml",
+ "toml 0.5.11",
  "yaml-rust",
 ]
 
@@ -975,9 +975,9 @@ dependencies = [
 
 [[package]]
 name = "either"
-version = "1.8.0"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
+checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "encoding_rs"
@@ -1244,7 +1244,7 @@ version = "0.13.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e"
 dependencies = [
- "ahash 0.8.2",
+ "ahash 0.8.3",
 ]
 
 [[package]]
@@ -1861,6 +1861,15 @@ dependencies = [
  "minimal-lexical",
 ]
 
+[[package]]
+name = "nom8"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "nu-ansi-term"
 version = "0.46.0"
@@ -2158,9 +2167,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.5.3"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4257b4a04d91f7e9e6290be5d3da4804dd5784fafde3a497d73eb2b4a158c30a"
+checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2168,9 +2177,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.3"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "241cda393b0cdd65e62e07e12454f1f25d57017dcc514b1514cd3c4645e3a0a6"
+checksum = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2178,9 +2187,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.3"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46b53634d8c8196302953c74d5352f33d0c512a9499bd2ce468fc9f4128fa27c"
+checksum = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2191,9 +2200,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.5.3"
+version = "2.5.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ef4f1332a8d4678b41966bb4cc1d0676880e84183a1ecc3f4b69f03e99c7a51"
+checksum = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d"
 dependencies = [
  "once_cell",
  "pest",
@@ -2665,9 +2674,9 @@ dependencies = [
 
 [[package]]
 name = "ructe"
-version = "0.16.0"
+version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3a08274953d9f290e34cf6e0335d784b76248dadff96381f94ab42e91e487555"
+checksum = "79c86c1631418815c5947a34be5872806586c65398754ec91cc2df35a8e26ba8"
 dependencies = [
  "base64 0.21.0",
  "bytecount",
@@ -2803,6 +2812,15 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "serde_spanned"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2c68e921cef53841b8925c2abadd27c9b891d9613bdc43d6b823062866df38e8"
+dependencies = [
+ "serde",
+]
+
 [[package]]
 name = "serde_urlencoded"
 version = "0.7.1"
@@ -3273,6 +3291,40 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "toml"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2f560bc7fb3eb31f5eee1340c68a2160cad39605b7b9c9ec32045ddbdee13b85"
+dependencies = [
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+ "toml_edit",
+]
+
+[[package]]
+name = "toml_datetime"
+version = "0.6.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "886f31a9b85b6182cabd4d8b07df3b451afcc216563748201490940d2a28ed36"
+dependencies = [
+ "serde",
+]
+
+[[package]]
+name = "toml_edit"
+version = "0.19.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "233d8716cdc5d20ec88a18a839edaf545edc71efa4a5ff700ef4a102c26cd8fa"
+dependencies = [
+ "indexmap",
+ "nom8",
+ "serde",
+ "serde_spanned",
+ "toml_datetime",
+]
+
 [[package]]
 name = "tonic"
 version = "0.8.3"
diff --git a/Cargo.toml b/Cargo.toml
index c78fad1..97edae6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -99,7 +99,7 @@ version = "0.7.0"
 anyhow = "1.0"
 dotenv = "0.15.0"
 ructe = { version = "0.16.0", features = ["sass", "mime03"] }
-toml = "0.5.8"
+toml = "0.7.0"
 
 [profile.dev.package.rsa]
 opt-level = 3

From b5138fc16d719ad2d8f93debd3b9a8eef7d9142a Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 29 Jan 2023 13:23:11 -0600
Subject: [PATCH 62/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index cb6e3aa..b9c5698 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,7 @@ checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.80"
+version = "0.3.81"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 97edae6..581f00a 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.80"
+version = "0.3.81"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From a952b528df9d8d0d2348c714ee1cf7f27f9d453d Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sun, 5 Feb 2023 21:09:47 -0600
Subject: [PATCH 63/87] Use transpose in a couple places

---
 src/db.rs | 74 +++++++++++++++++++++++++------------------------------
 1 file changed, 34 insertions(+), 40 deletions(-)

diff --git a/src/db.rs b/src/db.rs
index 6713cba..edf00c1 100644
--- a/src/db.rs
+++ b/src/db.rs
@@ -356,12 +356,12 @@ impl Db {
 
     pub(crate) async fn info(&self, actor_id: IriString) -> Result<Option<Info>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner.actor_id_info.get(actor_id.as_str().as_bytes())? {
-                let info = serde_json::from_slice(&ivec)?;
-                Ok(Some(info))
-            } else {
-                Ok(None)
-            }
+            inner
+                .actor_id_info
+                .get(actor_id.as_str().as_bytes())?
+                .map(|ivec| serde_json::from_slice(&ivec))
+                .transpose()
+                .map_err(Error::from)
         })
         .await
     }
@@ -390,12 +390,12 @@ impl Db {
 
     pub(crate) async fn instance(&self, actor_id: IriString) -> Result<Option<Instance>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner.actor_id_instance.get(actor_id.as_str().as_bytes())? {
-                let instance = serde_json::from_slice(&ivec)?;
-                Ok(Some(instance))
-            } else {
-                Ok(None)
-            }
+            inner
+                .actor_id_instance
+                .get(actor_id.as_str().as_bytes())?
+                .map(|ivec| serde_json::from_slice(&ivec))
+                .transpose()
+                .map_err(Error::from)
         })
         .await
     }
@@ -424,12 +424,12 @@ impl Db {
 
     pub(crate) async fn contact(&self, actor_id: IriString) -> Result<Option<Contact>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner.actor_id_contact.get(actor_id.as_str().as_bytes())? {
-                let contact = serde_json::from_slice(&ivec)?;
-                Ok(Some(contact))
-            } else {
-                Ok(None)
-            }
+            inner
+                .actor_id_contact
+                .get(actor_id.as_str().as_bytes())?
+                .map(|ivec| serde_json::from_slice(&ivec))
+                .transpose()
+                .map_err(Error::from)
         })
         .await
     }
@@ -454,22 +454,20 @@ impl Db {
 
     pub(crate) async fn media_id(&self, url: IriString) -> Result<Option<Uuid>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner.media_url_media_id.get(url.as_str().as_bytes())? {
-                Ok(uuid_from_ivec(ivec))
-            } else {
-                Ok(None)
-            }
+            Ok(inner
+                .media_url_media_id
+                .get(url.as_str().as_bytes())?
+                .and_then(uuid_from_ivec))
         })
         .await
     }
 
     pub(crate) async fn media_url(&self, id: Uuid) -> Result<Option<IriString>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner.media_id_media_url.get(id.as_bytes())? {
-                Ok(url_from_ivec(ivec))
-            } else {
-                Ok(None)
-            }
+            Ok(inner
+                .media_id_media_url
+                .get(id.as_bytes())?
+                .and_then(url_from_ivec))
         })
         .await
     }
@@ -509,26 +507,22 @@ impl Db {
         public_key_id: IriString,
     ) -> Result<Option<IriString>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner
+            Ok(inner
                 .public_key_id_actor_id
                 .get(public_key_id.as_str().as_bytes())?
-            {
-                Ok(url_from_ivec(ivec))
-            } else {
-                Ok(None)
-            }
+                .and_then(url_from_ivec))
         })
         .await
     }
 
     pub(crate) async fn actor(&self, actor_id: IriString) -> Result<Option<Actor>, Error> {
         self.unblock(move |inner| {
-            if let Some(ivec) = inner.actor_id_actor.get(actor_id.as_str().as_bytes())? {
-                let actor = serde_json::from_slice(&ivec)?;
-                Ok(Some(actor))
-            } else {
-                Ok(None)
-            }
+            inner
+                .actor_id_actor
+                .get(actor_id.as_str().as_bytes())?
+                .map(|ivec| serde_json::from_slice(&ivec))
+                .transpose()
+                .map_err(Error::from)
         })
         .await
     }

From 9b809913ad05a2ba773956bed6bee34d68ba3838 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 11 Feb 2023 18:16:06 -0600
Subject: [PATCH 64/87] Add note about JSON-LD problems

---
 README.md | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/README.md b/README.md
index ac22793..f177075 100644
--- a/README.md
+++ b/README.md
@@ -182,11 +182,17 @@ example, if the server is `https://relay.my.tld`, the correct URL would be
 - Add {anything}, the Add {anything} is relayed verbatim to listening servers.
     Note that this activity will likely be rejected by the listening servers unless it has been
     signed with a JSON-LD signature
+- Remove {anything}, the Remove {anything} is relayed verbatim to listening servers.
+    Note that this activity will likely be rejected by the listening servers unless it has been
+    signed with a JSON-LD signature
 
 ### Supported Discovery Protocols
 - Webfinger
 - NodeInfo
 
+### Known issues
+Pleroma and Akkoma do not support validating JSON-LD signatures, meaning many activities such as Delete, Update, Add, and Remove will be rejected with a message similar to `WARN: Response from https://example.com/inbox, "Invalid HTTP Signature"`. This is normal and not an issue with the relay.
+
 ### Contributing
 Feel free to open issues for anything you find an issue with. Please note that any contributed code will be licensed under the AGPLv3.
 

From 4a7775b56def7d778d6fbe489b64a660344d4fb7 Mon Sep 17 00:00:00 2001
From: perillamint <perillamint@silicon.moe>
Date: Sat, 17 Dec 2022 20:57:37 +0900
Subject: [PATCH 65/87] Misskey metadata support

This commit implements misskey metadata support and corresponding test
for From<MskyMeta> implementation

Also, it is good to note that, Misskey does not return 404 but 200 OK
when they poked at nonexistant endpoint, so the implementation should
handle for invalid json case
---
 src/error.rs         |   4 ++
 src/jobs/instance.rs | 148 +++++++++++++++++++++++++++++++++++++++----
 src/requests.rs      |  29 ++++++++-
 3 files changed, 165 insertions(+), 16 deletions(-)

diff --git a/src/error.rs b/src/error.rs
index 4818e3f..c72b8b5 100644
--- a/src/error.rs
+++ b/src/error.rs
@@ -30,6 +30,10 @@ impl Error {
     pub(crate) fn is_gone(&self) -> bool {
         matches!(self.kind, ErrorKind::Status(_, StatusCode::GONE))
     }
+
+    pub(crate) fn is_malformed_json(&self) -> bool {
+        matches!(self.kind, ErrorKind::Json(_))
+    }
 }
 
 impl std::fmt::Debug for Error {
diff --git a/src/jobs/instance.rs b/src/jobs/instance.rs
index 650c8ce..4713525 100644
--- a/src/jobs/instance.rs
+++ b/src/jobs/instance.rs
@@ -20,11 +20,41 @@ impl std::fmt::Debug for QueryInstance {
     }
 }
 
+enum InstanceApiType {
+    Mastodon,
+    Misskey,
+}
+
 impl QueryInstance {
     pub(crate) fn new(actor_id: IriString) -> Self {
         QueryInstance { actor_id }
     }
 
+    async fn get_instance(
+        instance_type: InstanceApiType,
+        state: &JobState,
+        scheme: &str,
+        authority: &str,
+    ) -> Result<Instance, Error> {
+        match instance_type {
+            InstanceApiType::Mastodon => {
+                let mastodon_instance_uri = iri!(format!("{scheme}://{authority}/api/v1/instance"));
+                state
+                    .requests
+                    .fetch_json::<Instance>(mastodon_instance_uri.as_str())
+                    .await
+            }
+            InstanceApiType::Misskey => {
+                let msky_meta_uri = iri!(format!("{scheme}://{authority}/api/meta"));
+                state
+                    .requests
+                    .fetch_json_msky::<MisskeyMeta>(msky_meta_uri.as_str())
+                    .await
+                    .map(|res| res.into())
+            }
+        }
+    }
+
     #[tracing::instrument(name = "Query instance", skip(state))]
     async fn perform(self, state: JobState) -> Result<(), Error> {
         let contact_outdated = state
@@ -45,23 +75,40 @@ impl QueryInstance {
             .authority_str()
             .ok_or(ErrorKind::MissingDomain)?;
         let scheme = self.actor_id.scheme_str();
-        let instance_uri = iri!(format!("{scheme}://{authority}/api/v1/instance"));
 
-        let instance = match state
-            .requests
-            .fetch_json::<Instance>(instance_uri.as_str())
-            .await
-        {
-            Ok(instance) => instance,
-            Err(e) if e.is_breaker() => {
-                tracing::debug!("Not retrying due to failed breaker");
+        // Attempt all endpoint.
+        let instance_futures = [
+            Self::get_instance(InstanceApiType::Mastodon, &state, scheme, authority),
+            Self::get_instance(InstanceApiType::Misskey, &state, scheme, authority),
+        ];
+
+        let mut instance_result: Option<Instance> = None;
+        for instance_future in instance_futures {
+            match instance_future.await {
+                Ok(instance) => {
+                    instance_result = Some(instance);
+                    break;
+                }
+                Err(e) if e.is_breaker() => {
+                    tracing::debug!("Not retrying due to failed breaker");
+                    return Ok(());
+                }
+                Err(e) if e.is_not_found() => {
+                    tracing::debug!("Server doesn't implement instance endpoint");
+                }
+                Err(e) if e.is_malformed_json() => {
+                    tracing::debug!("Server doesn't returned proper json");
+                }
+                Err(e) => return Err(e),
+            }
+        }
+
+        let instance = match instance_result {
+            Some(instance) => instance,
+            None => {
+                tracing::debug!("Server doesn't implement all instance endpoint");
                 return Ok(());
             }
-            Err(e) if e.is_not_found() => {
-                tracing::debug!("Server doesn't implement instance endpoint");
-                return Ok(());
-            }
-            Err(e) => return Err(e),
         };
 
         let description = instance.short_description.unwrap_or(instance.description);
@@ -144,12 +191,59 @@ struct Contact {
     avatar: IriString,
 }
 
+#[derive(serde::Deserialize)]
+#[serde(rename_all(deserialize = "camelCase"))]
+struct MisskeyMeta {
+    name: Option<String>,
+    description: Option<String>,
+    version: String,
+    maintainer_name: Option<String>,
+    // Yes, I know, this is instance URL... but we does not have any choice.
+    uri: IriString,
+    // Use instance icon as a profile picture...
+    icon_url: Option<IriString>,
+    features: MisskeyFeatures,
+}
+
+#[derive(serde::Deserialize)]
+struct MisskeyFeatures {
+    registration: Boolish, // Corresponding to Mastodon registration
+}
+
+impl From<MisskeyMeta> for Instance {
+    fn from(meta: MisskeyMeta) -> Self {
+        let contact = match (meta.maintainer_name, meta.icon_url) {
+            (Some(maintainer), Some(icon)) => Some(Contact {
+                username: maintainer.clone(),
+                display_name: maintainer,
+                url: meta.uri,
+                avatar: icon,
+            }),
+            (_, _) => None,
+        };
+
+        // Transform it into Mastodon Instance object
+        Instance {
+            title: meta.name.unwrap_or_else(|| "".to_owned()),
+            short_description: None,
+            description: meta.description.unwrap_or_else(|| "".to_owned()),
+            version: meta.version,
+            registrations: meta.features.registration,
+            approval_required: false,
+            contact,
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use super::Instance;
+    use super::MisskeyMeta;
 
     const ASONIX_INSTANCE: &str = r#"{"uri":"masto.asonix.dog","title":"asonix.dog","short_description":"The asonix of furry mastodon. For me and a few friends. DM me somewhere if u want an account lol","description":"A mastodon server that's only for me and nobody else sorry","email":"asonix@asonix.dog","version":"4.0.0rc2-asonix-changes","urls":{"streaming_api":"wss://masto.asonix.dog"},"stats":{"user_count":7,"status_count":12328,"domain_count":5146},"thumbnail":"https://masto.asonix.dog/system/site_uploads/files/000/000/002/@1x/32f51462a2b2bf2d.png","languages":["dog"],"registrations":false,"approval_required":false,"invites_enabled":false,"configuration":{"accounts":{"max_featured_tags":10},"statuses":{"max_characters":500,"max_media_attachments":4,"characters_reserved_per_url":23},"media_attachments":{"supported_mime_types":["image/jpeg","image/png","image/gif","image/heic","image/heif","image/webp","image/avif","video/webm","video/mp4","video/quicktime","video/ogg","audio/wave","audio/wav","audio/x-wav","audio/x-pn-wave","audio/vnd.wave","audio/ogg","audio/vorbis","audio/mpeg","audio/mp3","audio/webm","audio/flac","audio/aac","audio/m4a","audio/x-m4a","audio/mp4","audio/3gpp","video/x-ms-asf"],"image_size_limit":10485760,"image_matrix_limit":16777216,"video_size_limit":41943040,"video_frame_rate_limit":60,"video_matrix_limit":2304000},"polls":{"max_options":4,"max_characters_per_option":50,"min_expiration":300,"max_expiration":2629746}},"contact_account":{"id":"1","username":"asonix","acct":"asonix","display_name":"Liom on Mane :antiverified:","locked":true,"bot":false,"discoverable":true,"group":false,"created_at":"2021-02-09T00:00:00.000Z","note":"\u003cp\u003e26, local liom, friend, rust (lang) stan, bi \u003c/p\u003e\u003cp\u003eicon by \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://furaffinity.net/user/lalupine\" target=\"blank\" rel=\"noopener noreferrer\" class=\"u-url mention\"\u003e@\u003cspan\u003elalupine@furaffinity.net\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003cbr /\u003eheader by \u003cspan class=\"h-card\"\u003e\u003ca href=\"https://furaffinity.net/user/tronixx\" target=\"blank\" rel=\"noopener noreferrer\" class=\"u-url mention\"\u003e@\u003cspan\u003etronixx@furaffinity.net\u003c/span\u003e\u003c/a\u003e\u003c/span\u003e\u003c/p\u003e\u003cp\u003eTestimonials:\u003c/p\u003e\u003cp\u003eStand: LIONS\u003cbr /\u003eStand User: AODE\u003cbr /\u003e- Keris (not on here)\u003c/p\u003e","url":"https://masto.asonix.dog/@asonix","avatar":"https://masto.asonix.dog/system/accounts/avatars/000/000/001/original/00852df0e6fee7e0.png","avatar_static":"https://masto.asonix.dog/system/accounts/avatars/000/000/001/original/00852df0e6fee7e0.png","header":"https://masto.asonix.dog/system/accounts/headers/000/000/001/original/8122ce3e5a745385.png","header_static":"https://masto.asonix.dog/system/accounts/headers/000/000/001/original/8122ce3e5a745385.png","followers_count":237,"following_count":474,"statuses_count":8798,"last_status_at":"2022-11-08","noindex":true,"emojis":[{"shortcode":"antiverified","url":"https://masto.asonix.dog/system/custom_emojis/images/000/030/053/original/bb0bc2e395b9a127.png","static_url":"https://masto.asonix.dog/system/custom_emojis/images/000/030/053/static/bb0bc2e395b9a127.png","visible_in_picker":true}],"fields":[{"name":"pronouns","value":"he/they","verified_at":null},{"name":"software","value":"bad","verified_at":null},{"name":"gitea","value":"\u003ca href=\"https://git.asonix.dog\" target=\"_blank\" rel=\"nofollow noopener noreferrer me\"\u003e\u003cspan class=\"invisible\"\u003ehttps://\u003c/span\u003e\u003cspan class=\"\"\u003egit.asonix.dog\u003c/span\u003e\u003cspan class=\"invisible\"\u003e\u003c/span\u003e\u003c/a\u003e","verified_at":null},{"name":"join my","value":"relay","verified_at":null}]},"rules":[]}"#;
     const HYNET_INSTANCE: &str = r#"{"approval_required":false,"avatar_upload_limit":2000000,"background_image":"https://soc.hyena.network/images/city.jpg","background_upload_limit":4000000,"banner_upload_limit":4000000,"description":"Akkoma: The cooler fediverse server","description_limit":5000,"email":"me@hyena.network","languages":["en"],"max_toot_chars":"5000","pleroma":{"metadata":{"account_activation_required":true,"features":["pleroma_api","mastodon_api","mastodon_api_streaming","polls","v2_suggestions","pleroma_explicit_addressing","shareable_emoji_packs","multifetch","pleroma:api/v1/notifications:include_types_filter","chat","shout","relay","safe_dm_mentions","pleroma_emoji_reactions","pleroma_chat_messages","exposable_reactions","profile_directory","custom_emoji_reactions"],"federation":{"enabled":true,"exclusions":false,"mrf_hashtag":{"federated_timeline_removal":[],"reject":[],"sensitive":["nsfw"]},"mrf_policies":["SimplePolicy","EnsureRePrepended","HashtagPolicy"],"mrf_simple":{"accept":[],"avatar_removal":[],"banner_removal":[],"federated_timeline_removal":["botsin.space"],"followers_only":[],"media_nsfw":["mstdn.jp","wxw.moe","knzk.me","vipgirlfriend.xxx","humblr.social","switter.at","kinkyelephant.com","sinblr.com","kinky.business","rubber.social"],"media_removal":[],"reject":["*.10minutepleroma.com","101010.pl","13bells.com","2.distsn.org","2hu.club","2ndamendment.social","434.earth","4chan.icu","4qq.org","7td.org","80percent.social","a.nti.social","aaathats3as.com","accela.online","amala.schwartzwelt.xyz","angrytoday.com","anime.website","antitwitter.moe","antivaxxer.icu","archivefedifor.fun","artalley.social","bae.st","bajax.us","baraag.net","bbs.kawa-kun.com","beefyboys.club","beefyboys.win","bikeshed.party","bitcoinhackers.org","bleepp.com","blovice.bahnhof.cz","brighteon.social","buildthatwallandmakeamericagreatagain.trumpislovetrumpis.life","bungle.online","cawfee.club","censorship.icu","chungus.cc","club.darknight-coffee.org","clubcyberia.co","cock.fish","cock.li","comfyboy.club","contrapointsfan.club","coon.town","counter.social","cum.salon","d-fens.systems","definitely-not-archivefedifor.fun","degenerates.fail","desuposter.club","detroitriotcity.com","developer.gab.com","dogwhipping.day","eientei.org","enigmatic.observer","eveningzoo.club","exited.eu","federation.krowverse.services","fedi.cc","fedi.krowverse.services","fedi.pawlicker.com","fedi.vern.cc","freak.university","freeatlantis.com","freecumextremist.com","freesoftwareextremist.com","freespeech.firedragonstudios.com","freespeech.host","freespeechextremist.com","freevoice.space","freezepeach.xyz","froth.zone","fuckgov.org","gab.ai","gab.polaris-1.work","gab.protohype.net","gabfed.com","gameliberty.club","gearlandia.haus","gitmo.life","glindr.org","glittersluts.xyz","glowers.club","godspeed.moe","gorf.pub","goyim.app","gs.kawa-kun.com","hagra.net","hallsofamenti.io","hayu.sh","hentai.baby","honkwerx.tech","hunk.city","husk.site","iddqd.social","ika.moe","isexychat.space","jaeger.website","justicewarrior.social","kag.social","katiehopkinspolitical.icu","kiwifarms.cc","kiwifarms.is","kiwifarms.net","kohrville.net","koyu.space","kys.moe","lain.com","lain.sh","leafposter.club","lets.saynoto.lgbt","liberdon.com","libertarianism.club","ligma.pro","lolis.world","masochi.st","masthead.social","mastodon.digitalsuccess.dev","mastodon.fidonet.io","mastodon.grin.hu","mastodon.ml","midnightride.rs","milker.cafe","mobile.tmediatech.io","moon.holiday","mstdn.foxfam.club","mstdn.io","mstdn.starnix.network","mulmeyun.church","nazi.social","neckbeard.xyz","neenster.org","neko.ci","netzsphaere.xyz","newjack.city","nicecrew.digital","nnia.space","noagendasocial.com","norrebro.space","oursocialism.today","ovo.sc","pawoo.net","paypig.org","pedo.school","phreedom.tk","pieville.net","pkteerium.xyz","pl.murky.club","pl.spiderden.net","pl.tkammer.de","pl.zombiecats.run","pleroma.nobodyhasthe.biz","pleroma.runfox.tk","pleroma.site","plr.inferencium.net","pmth.us","poa.st","pod.vladtepesblog.com","political.icu","pooper.social","posting.lolicon.rocks","preteengirls.biz","prout.social","qoto.org","rage.lol","rakket.app","raplst.town","rdrama.cc","ryona.agency","s.sneak.berlin","seal.cafe","sealion.club","search.fedi.app","sementerrori.st","shitposter.club","shortstackran.ch","silkhe.art","sleepy.cafe","soc.mahodou.moe","soc.redeyes.site","social.076.ne.jp","social.anoxinon.de","social.chadland.net","social.freetalklive.com","social.getgle.org","social.handholding.io","social.headsca.la","social.imirhil.fr","social.lovingexpressions.net","social.manalejandro.com","social.midwaytrades.com","social.pseudo-whiskey.bar","social.targaryen.house","social.teci.world","societal.co","society.oftrolls.com","socks.pinnoto.org","socnet.supes.com","solagg.com","spinster.xyz","springbo.cc","stereophonic.space","sunshinegardens.org","theautisticinvestors.quest","thechad.zone","theduran.icu","theosis.church","toot.love","toots.alirezahayati.com","traboone.com","truthsocial.co.in","truthsocial.com","tuusin.misono-ya.info","tweety.icu","unbound.social","unsafe.space","varishangout.net","video.nobodyhasthe.biz","voicenews.icu","voluntaryism.club","waifu.social","weeaboo.space","whinge.town","wolfgirl.bar","workers.dev","wurm.host","xiii.ch","xn--p1abe3d.xn--80asehdb","yggdrasil.social","youjo.love"],"reject_deletes":[],"report_removal":[]},"mrf_simple_info":{"federated_timeline_removal":{"botsin.space":{"reason":"A lot of bot content"}},"media_nsfw":{"humblr.social":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"kinky.business":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"kinkyelephant.com":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"knzk.me":{"reason":"Unmarked nsfw media"},"mstdn.jp":{"reason":"Not sure about the media policy"},"rubber.social":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"sinblr.com":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"switter.at":{"reason":"NSFW Instance, safe to assume most content is NSFW"},"vipgirlfriend.xxx":{"reason":"Unmarked nsfw media"},"wxw.moe":{"reason":"Unmarked nsfw media"}}},"quarantined_instances":[],"quarantined_instances_info":{"quarantined_instances":{}}},"fields_limits":{"max_fields":10,"max_remote_fields":20,"name_length":512,"value_length":2048},"post_formats":["text/plain","text/html","text/markdown","text/bbcode","text/x.misskeymarkdown"],"privileged_staff":false},"stats":{"mau":1},"vapid_public_key":"BMg4q-rT3rkMzc29F7OS5uM6t-Rx4HncMIB1NXrKwNlVRfX-W1kwgOuq5pDy-WhWmOZudaegftjBTCX3-pzdDFc"},"poll_limits":{"max_expiration":31536000,"max_option_chars":200,"max_options":20,"min_expiration":0},"registrations":"FALSE","shout_limit":5000,"stats":{"domain_count":1035,"status_count":7,"user_count":1},"thumbnail":"https://soc.hyena.network/instance/thumbnail.jpeg","title":"HyNET Social","upload_limit":16000000,"uri":"https://soc.hyena.network","urls":{"streaming_api":"wss://soc.hyena.network"},"version":"2.7.2 (compatible; Akkoma 3.0.0)"}"#;
+    const MISSKEY_BARE_INSTANCE: &str = r#"{"maintainerName":null,"maintainerEmail":null,"version":"12.119.2","name":null,"uri":"https://msky-lab-01.arewesecureyet.org","description":null,"langs":[],"tosUrl":null,"repositoryUrl":"https://github.com/misskey-dev/misskey","feedbackUrl":"https://github.com/misskey-dev/misskey/issues/new","disableRegistration":false,"disableLocalTimeline":false,"disableGlobalTimeline":false,"driveCapacityPerLocalUserMb":1024,"driveCapacityPerRemoteUserMb":32,"emailRequiredForSignup":false,"enableHcaptcha":false,"hcaptchaSiteKey":null,"enableRecaptcha":false,"recaptchaSiteKey":null,"swPublickey":null,"themeColor":null,"mascotImageUrl":"/assets/ai.png","bannerUrl":null,"errorImageUrl":"https://xn--931a.moe/aiart/yubitun.png","iconUrl":null,"backgroundImageUrl":null,"logoImageUrl":null,"maxNoteTextLength":3000,"emojis":[],"defaultLightTheme":null,"defaultDarkTheme":null,"ads":[],"enableEmail":false,"enableTwitterIntegration":false,"enableGithubIntegration":false,"enableDiscordIntegration":false,"enableServiceWorker":false,"translatorAvailable":false,"pinnedPages":["/featured","/channels","/explore","/pages","/about-misskey"],"pinnedClipId":null,"cacheRemoteFiles":true,"requireSetup":false,"proxyAccountName":null,"features":{"registration":true,"localTimeLine":true,"globalTimeLine":true,"emailRequiredForSignup":false,"elasticsearch":false,"hcaptcha":false,"recaptcha":false,"objectStorage":false,"twitter":false,"github":false,"discord":false,"serviceWorker":false,"miauth":true}}"#;
+    const MISSKEY_STELLA_INSTANCE: &str = r###"{"maintainerName":"Caipira","maintainerEmail":"caipira@sagestn.one","version":"12.120.0-alpha.8+cs","name":"Stella","uri":"https://stella.place","description":"<center>무수히 많은 별 중 하나인 인스턴스입니다.</center>\n<center>SINCE 2022. 5. 8. ~</center>\n<center>|</center>\n<b><center>Enable</center></b>\n<small>Castella = Misskey fork (.....)</small>","langs":[],"tosUrl":"https://docs.stella.place/tos","repositoryUrl":"https://github.com/misskey-dev/misskey","feedbackUrl":"https://github.com/misskey-dev/misskey/issues/new","disableRegistration":false,"disableLocalTimeline":false,"disableGlobalTimeline":false,"driveCapacityPerLocalUserMb":3072,"driveCapacityPerRemoteUserMb":32,"emailRequiredForSignup":true,"enableHcaptcha":true,"hcaptchaSiteKey":"94d629f6-a38e-4f24-83dd-63326c7e3bbf","enableRecaptcha":false,"recaptchaSiteKey":"6Lf-9dIfAAAAAF0Jp_QSsIlltyi371ZSU48Csisy","enableTurnstile":false,"turnstileSiteKey":"0x4AAAAAAAArrDq-OcfsyU-R","swPublickey":"BNTI1ms29LPGpdF8spPKa5khs6B2UYnVWa3KcO6e6JJoVXzbCBjdUdpkZHo-MK_AZfJxbTE8Z8C7g5kQChEkfp8","themeColor":"#df99f7","mascotImageUrl":"/assets/ai.png","bannerUrl":"https://cdn.stella.place/assets/bg.jpg","errorImageUrl":"https://xn--931a.moe/aiart/yubitun.png","iconUrl":"https://cdn.stella.place/assets/Stella.png","backgroundImageUrl":"https://cdn.stella.place/assets/bg.jpg","logoImageUrl":null,"maxNoteTextLength":3000,"emojis":[{"id":"97f9mubsmt","aliases":[""],"name":"big_blobhaj_hug","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/15d27c96-093a-4dc0-ae57-b848180b073b.png"},{"id":"97f9rzt5ok","aliases":[""],"name":"blobhaj","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/fb06df30-00d8-4b3b-ac8c-ee779ff06599.png"},{"id":"97f9rzjso5","aliases":[""],"name":"blobhaj_asparagus","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/35ed1236-8ebc-4c91-a793-0cfd04532148.png"},{"id":"97f9p8gtn3","aliases":[""],"name":"blobhaj_blanket_blue","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/d5876a69-1dd3-4e6a-b3cd-d497c06064fa.png"},{"id":"97f9p8gonf","aliases":[""],"name":"blobhaj_blanket_slate","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/43c461e7-f8af-4636-b72a-6d0ef40c2655.png"},{"id":"97f9rzl7nt","aliases":[""],"name":"blobhaj_blobby_hug","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/8a272ac5-b9d7-4554-ab18-7088f6132bc3.png"},{"id":"97f9rzmjo7","aliases":[""],"name":"blobhaj_full_body_hug","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/9f8251d0-c816-441e-9eef-2687502023fc.png"},{"id":"97f9rzl0ns","aliases":[""],"name":"blobhaj_heart","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/48ec936e-ae27-4b7c-94db-b673b628e231.png"},{"id":"97f9gwvvl8","aliases":[""],"name":"blobhaj_mdbook","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/56fdbaa3-06e6-4f5d-81d6-3e8e54ae059c.png"},{"id":"97f9rzk7nq","aliases":[""],"name":"blobhaj_mlem","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/03ea3ae0-2d40-4faf-8d3c-10f788a3de1d.png"},{"id":"97f9fpovkq","aliases":[""],"name":"blobhaj_octobook","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/6e992574-d8ca-4592-80a0-4f7bdff03cf8.png"},{"id":"97f9rzpjoc","aliases":[""],"name":"blobhaj_pride_heart","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/c397da98-dd44-484e-8de4-7db11a677e42.png"},{"id":"97f9rzjko4","aliases":[""],"name":"blobhaj_reach","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/e2c00652-a2f6-4ccf-bf0e-796f85b7854d.png"},{"id":"97f9rzjxo6","aliases":[""],"name":"blobhaj_sad_reach","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/bf36e678-20fd-49cc-8485-3ae5b8db033e.png"},{"id":"97f9rzqxod","aliases":[""],"name":"blobhaj_shock","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/ab9a3062-3bda-48c3-a91a-95beb86d56cc.png"},{"id":"97f9rzo0oa","aliases":[""],"name":"blobhaj_tiny_heart","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/aec32c7c-2b53-4251-b3ba-862587fa6ff6.png"},{"id":"97f9rznto8","aliases":[""],"name":"blobhaj_trans_pride_heart","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/e0dad2d0-9136-4310-8841-7bf3819ba152.png"},{"id":"97f9k7iqm2","aliases":[""],"name":"sir_blobhaj","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/70546774-e704-4a93-ab28-059ef3c54b65.png"},{"id":"97f9ikojll","aliases":[""],"name":"sir_blobhaj_stern","category":"Blobhaj Hub","host":null,"url":"https://cdn.stella.place/D1/2d69a377-a562-4769-8f60-b3ab8794b2a2.png"},{"id":"953ytptaah","aliases":[""],"name":"ysoyaboom","category":"Blue Archive","host":null,"url":"https://cdn.stella.place/D1/51240ea1-345e-4d43-a293-300dc968197a.gif"},{"id":"953ytpt8ag","aliases":[""],"name":"ysoyasnap","category":"Blue Archive","host":null,"url":"https://cdn.stella.place/D1/e95337b8-499b-47b2-811e-e1f4398efc69.gif"},{"id":"97q78i6ss2","aliases":[""],"name":"terminal_blinker","category":"Dev","host":null,"url":"https://cdn.stella.place/D1/a04022ea-d8dc-4861-a7fd-360d178bd01f.png"},{"id":"97v0x375vq","aliases":[],"name":"ff14_msq","category":"FF14","host":null,"url":"https://cdn.stella.place/D1/db14bccd-8f89-428b-b1b9-8da7e821656b.png"},{"id":"97v0x375jq","aliases":[],"name":"ff14_msq_done","category":"FF14","host":null,"url":"https://cdn.stella.place/D1/7be4bb6d-9271-4e40-abaf-24fe97ec9a76.png"},{"id":"97v0x37yjs","aliases":[],"name":"ff14_msq_locked","category":"FF14","host":null,"url":"https://cdn.stella.place/D1/e2c85711-032b-4a83-b933-24e8a96ece82.png"},{"id":"9542b9c4io","aliases":["사이노"],"name":"cyno_oops","category":"Genshin Impact","host":null,"url":"https://cdn.stella.place/D1/2507ad57-b042-407d-a84e-e676ea8710c5.gif"},{"id":"97lo6lbcin","aliases":["합니다"],"name":"kr_doing","category":"KR","host":null,"url":"https://cdn.stella.place/D1/eeee5f16-ac99-42e7-8c4c-c773150d4bd5.png"},{"id":"97lo6u3zqa","aliases":["정상"],"name":"kr_normal","category":"KR","host":null,"url":"https://cdn.stella.place/D1/29e82750-da88-4baf-a8ec-64b4bcafdf28.png"},{"id":"97lo7523j2","aliases":["우리"],"name":"kr_our","category":"KR","host":null,"url":"https://cdn.stella.place/D1/458304e1-72e3-4fd2-87d4-c05a6a152083.png"},{"id":"97lo6zujj0","aliases":["식당"],"name":"kr_restaurant","category":"KR","host":null,"url":"https://cdn.stella.place/D1/e257d140-e8fe-477a-b5be-4e7e29239544.png"},{"id":"97lo6q34ir","aliases":["영업"],"name":"kr_sales","category":"KR","host":null,"url":"https://cdn.stella.place/D1/2331cb3a-5ca5-42ae-b677-691f8fe3b4e4.png"},{"id":"96kc58706a","aliases":[""],"name":"Kirkland_Signature","category":"Logo","host":null,"url":"https://cdn.stella.place/D1/b24c722a-0cf3-485c-8bb6-e8385e2dcd2b.png"},{"id":"95dwescv8x","aliases":[""],"name":"ms_angry","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/08407ba0-eb70-4385-ad7e-7987a1b178b8.png"},{"id":"95dwdph489","aliases":[""],"name":"ms_balloon","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/d3e49618-d9fb-4142-b369-b8b0a19f6875.png"},{"id":"95dwcb0w7c","aliases":[""],"name":"ms_contempt","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/b89d5827-d4ca-40d8-b250-02de2ab44ed9.png"},{"id":"95dwe68v8j","aliases":[""],"name":"ms_lie","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/889a793d-07a7-4f1f-a6a8-a151ed4ce1e3.png"},{"id":"95dwa1yc5x","aliases":[""],"name":"ms_mastodon","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/75fce83f-50a4-4ae9-86f3-52882279ccfd.png"},{"id":"95dwgcp0a8","aliases":[""],"name":"ms_messgaki","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/a432b00e-0ba0-4e13-aa25-1b6b61469807.png"},{"id":"95dwfs4h9q","aliases":[""],"name":"ms_messgaki_normal","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/5b9e1a10-f4af-4d35-af4f-a1cca7df5454.png"},{"id":"95dwb9i26m","aliases":[""],"name":"ms_messtodon","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/a2c7ff09-3090-445d-be8b-68144ac59e5a.png"},{"id":"95dwdbym81","aliases":[""],"name":"ms_sleepy","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/bbf5648e-6deb-4f3d-9fc0-6f9d1bbccd40.png"},{"id":"95dwf76i98","aliases":[""],"name":"ms_small_messgaki","category":"Messtodon","host":null,"url":"https://cdn.stella.place/D1/430b9d2a-591e-4beb-a037-fea66c777319.png"},{"id":"97pjdnpp76","aliases":["42"],"name":"text_42","category":"TEXT","host":null,"url":"https://cdn.stella.place/D1/e253653a-94b0-4cad-9277-f9c8e1188c5f.png"},{"id":"96njxnbkgt","aliases":[""],"name":"yt_social_circle_dark","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-0e0615fe-c430-43c2-910b-c9eea6ebf5ab.png"},{"id":"96njxneyh4","aliases":[""],"name":"yt_social_circle_red","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-7780f3d7-c0ed-46c8-93f2-afa01c39c65e.png"},{"id":"96njxnazgp","aliases":[""],"name":"yt_social_circle_white","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-ce023618-077a-4e80-8c37-827bd1490803.png"},{"id":"96njxnb8gr","aliases":[""],"name":"yt_social_square_dark","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-c48f67f6-6b46-4101-a8ba-123f5fa2508d.png"},{"id":"96njxnc7gv","aliases":[""],"name":"yt_social_square_red","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-51e24c3e-d8a7-4f52-b342-718823fc9631.png"},{"id":"96njxngrh7","aliases":[""],"name":"yt_social_square_white","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-de69c7e1-7044-4eab-b53f-7629342bcb11.png"},{"id":"96njxnbags","aliases":[""],"name":"yt_social_squircle_dark","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-de763d0f-3659-463e-b9b4-f6975a007b37.png"},{"id":"96njxnh5ha","aliases":[""],"name":"yt_social_squircle_red","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-a7e847b3-23ad-40ad-a06e-f6eafe23e001.png"},{"id":"96njxnb4gq","aliases":[""],"name":"yt_social_squircle_white","category":"YouTube Brand resources","host":null,"url":"https://cdn.stella.place/D1/webpublic-7d1878a0-e2a8-4336-a6f8-094a4b44a759.png"},{"id":"937z342qj0","aliases":[""],"name":"blackverified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/496d2618-4a32-41a8-a1ba-df798a16f209.gif"},{"id":"937zd787m6","aliases":[""],"name":"blueviolet_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/357c3a1e-88d0-47f3-9812-5f1f15dec382.gif"},{"id":"937z127ui9","aliases":[""],"name":"freshair_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/7d10a1b1-8128-4400-af63-f28d4c3c9888.gif"},{"id":"937zkingmk","aliases":[""],"name":"fuchsia_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/5cf05079-8216-40ca-875d-8cacb546e1f9.gif"},{"id":"937zhe1mmg","aliases":[""],"name":"lightred_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/abd3c0f9-d046-4549-9d1e-f018d92982bf.gif"},{"id":"937zfpirmc","aliases":[""],"name":"mangotango_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/9c4de8ba-2c63-41bb-b581-e3e52e2017be.gif"},{"id":"937ziz3lmi","aliases":[""],"name":"middleyellow_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/86a74a5f-51e9-40f8-b2fd-de56927b72b0.gif"},{"id":"937zlhbumm","aliases":[""],"name":"palelavender_verifiedX","category":"verified","host":null,"url":"https://cdn.stella.place/D1/6364fb55-8c48-49b9-9cb9-2a06f50a920a.gif"},{"id":"937xqp173v","aliases":[""],"name":"pink_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/41f5eb90-86f5-4955-9de5-5439293b2a90.gif"},{"id":"937z46vbje","aliases":[""],"name":"red_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/bac2a25a-b79b-42db-bc75-f398dc18b2d1.gif"},{"id":"937yrlcvfv","aliases":[""],"name":"turquoise_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/2ff8d332-5563-4951-a2dc-c627fc5c1ff1.gif"},{"id":"937atf86py","aliases":[""],"name":"verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/654525f0-a8f3-415f-9051-c79739f72c31.gif"},{"id":"937yzdnihz","aliases":[""],"name":"vividred_verified","category":"verified","host":null,"url":"https://cdn.stella.place/D1/3d06e1ef-372b-4d22-9d80-02e836b911b1.gif"},{"id":"98px6gj0a9","aliases":["엘렐레"],"name":"gardeneel_ellelle","category":null,"host":null,"url":"https://cdn.stella.place/D1/c5810e07-57ad-4fd8-ae86-753e2dd799d1.png"},{"id":"98pw3pndpo","aliases":["메롱","엘렐레"],"name":"gardeneel_tongue","category":null,"host":null,"url":"https://cdn.stella.place/D1/877b2ca3-6540-4d77-a061-f1a5e047e147.png"},{"id":"97rs46kkuz","aliases":["자빠"],"name":"yum_1","category":null,"host":null,"url":"https://cdn.stella.place/D1/74d00105-84fc-4050-8bd0-28d16abba3dd.png"},{"id":"97rs4w2ubs","aliases":["지게"],"name":"yum_2","category":null,"host":null,"url":"https://cdn.stella.place/D1/8cd4b526-d42f-42af-b3a5-6f6502798866.png"},{"id":"97rs593z6t","aliases":["맛있ㅇ"],"name":"yum_3","category":null,"host":null,"url":"https://cdn.stella.place/D1/095eba74-7862-4719-aa09-5ad28aa7d29a.png"},{"id":"97rs5lph70","aliases":["ㅓ요"],"name":"yum_4","category":null,"host":null,"url":"https://cdn.stella.place/D1/1d28ee5a-dd45-4fb0-bb65-a96ee20ed971.png"}],"defaultLightTheme":null,"defaultDarkTheme":null,"ads":[],"enableEmail":true,"enableTwitterIntegration":false,"enableGithubIntegration":false,"enableDiscordIntegration":true,"enableServiceWorker":true,"translatorAvailable":false,"pinnedPages":["/featured","/channels","/explore","/pages","/about-misskey"],"pinnedClipId":null,"cacheRemoteFiles":true,"requireSetup":false,"proxyAccountName":"proxy","features":{"registration":true,"localTimeLine":true,"globalTimeLine":true,"emailRequiredForSignup":true,"elasticsearch":false,"hcaptcha":true,"recaptcha":false,"turnstile":false,"objectStorage":true,"twitter":false,"github":false,"discord":true,"serviceWorker":true,"miauth":true}}"###;
 
     #[test]
     fn deser_masto_instance_with_contact() {
@@ -162,4 +256,30 @@ mod tests {
         let inst: Instance = serde_json::from_str(HYNET_INSTANCE).unwrap();
         assert!(inst.contact.is_none());
     }
+
+    #[test]
+    fn deser_misskey_instance_without_contact() {
+        let meta: MisskeyMeta = serde_json::from_str(MISSKEY_BARE_INSTANCE).unwrap();
+        assert!(meta.icon_url.is_none());
+    }
+
+    #[test]
+    fn deser_misskey_instance_with_contact() {
+        let meta: MisskeyMeta = serde_json::from_str(MISSKEY_STELLA_INSTANCE).unwrap();
+        assert_eq!(
+            meta.icon_url.unwrap(),
+            "https://cdn.stella.place/assets/Stella.png"
+        );
+    }
+
+    #[test]
+    fn deser_misskey_instance_into() {
+        let meta: MisskeyMeta = serde_json::from_str(MISSKEY_STELLA_INSTANCE).unwrap();
+        let inst: Instance = meta.into();
+
+        assert_eq!(
+            inst.contact.unwrap().avatar,
+            "https://cdn.stella.place/assets/Stella.png"
+        );
+    }
 }
diff --git a/src/requests.rs b/src/requests.rs
index 18b9840..f5ecc86 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -257,6 +257,14 @@ impl Requests {
         self.do_fetch(url, "application/json").await
     }
 
+    #[tracing::instrument(name = "Fetch Json", skip(self), fields(signing_string))]
+    pub(crate) async fn fetch_json_msky<T>(&self, url: &str) -> Result<T, Error>
+    where
+        T: serde::de::DeserializeOwned,
+    {
+        self.do_fetch_msky(url, "application/json").await
+    }
+
     #[tracing::instrument(name = "Fetch Activity+Json", skip(self), fields(signing_string))]
     pub(crate) async fn fetch<T>(&self, url: &str) -> Result<T, Error>
     where
@@ -266,6 +274,20 @@ impl Requests {
     }
 
     async fn do_fetch<T>(&self, url: &str, accept: &str) -> Result<T, Error>
+    where
+        T: serde::de::DeserializeOwned,
+    {
+        self.do_fetch_inner(url, accept, false).await
+    }
+
+    async fn do_fetch_msky<T>(&self, url: &str, accept: &str) -> Result<T, Error>
+    where
+        T: serde::de::DeserializeOwned,
+    {
+        self.do_fetch_inner(url, accept, true).await
+    }
+
+    async fn do_fetch_inner<T>(&self, url: &str, accept: &str, use_post: bool) -> Result<T, Error>
     where
         T: serde::de::DeserializeOwned,
     {
@@ -279,8 +301,11 @@ impl Requests {
         let span = tracing::Span::current();
 
         let client: Client = self.client.borrow().clone();
-        let res = client
-            .get(url)
+        let client_req = match use_post {
+            true => client.post(url),
+            false => client.get(url),
+        };
+        let res = client_req
             .insert_header(("Accept", accept))
             .insert_header(Date(SystemTime::now().into()))
             .signature(

From 667d586160b1262923bd81f6d0fb9793577a3281 Mon Sep 17 00:00:00 2001
From: perillamint <perillamint@silicon.moe>
Date: Thu, 5 Jan 2023 00:53:00 +0900
Subject: [PATCH 66/87] Send dummy JSON when trying Misskey API endpoint

From Misskey 13, Misskey expects valid JSON (does not care its content
though) in POST body. To workaround this, send empty JSON object when
requesting Misskey API endpoint
---
 src/requests.rs | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/src/requests.rs b/src/requests.rs
index f5ecc86..304d0a6 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -305,7 +305,7 @@ impl Requests {
             true => client.post(url),
             false => client.get(url),
         };
-        let res = client_req
+        let client_signed = client_req
             .insert_header(("Accept", accept))
             .insert_header(Date(SystemTime::now().into()))
             .signature(
@@ -316,9 +316,15 @@ impl Requests {
                     span.in_scope(|| signer.sign(signing_string))
                 },
             )
-            .await?
-            .send()
-            .await;
+            .await?;
+        let res = match use_post {
+            true => {
+                let dummy = serde_json::json!({});
+                client_signed.send_json(&dummy)
+            }
+            false => client_signed.send(),
+        }
+        .await;
 
         let mut res = self.check_response(&parsed_url, res).await?;
 

From a1ea5d676c63298e52d6c345a728e60fd185a79e Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 25 Feb 2023 15:02:16 -0600
Subject: [PATCH 67/87] Rework misskey fetch to reuse deliver plumbing

Only count server errors towards failed breakers
---
 src/data/actor.rs          |   2 +-
 src/jobs/contact.rs        |   2 +-
 src/jobs/deliver.rs        |   2 +-
 src/jobs/instance.rs       |   4 +-
 src/jobs/nodeinfo.rs       |   4 +-
 src/middleware/verifier.rs |   6 +-
 src/requests.rs            | 123 +++++++++++++++++--------------------
 src/routes/media.rs        |   2 +-
 8 files changed, 67 insertions(+), 78 deletions(-)

diff --git a/src/data/actor.rs b/src/data/actor.rs
index 784e99f..af6fb78 100644
--- a/src/data/actor.rs
+++ b/src/data/actor.rs
@@ -71,7 +71,7 @@ impl ActorCache {
         id: &IriString,
         requests: &Requests,
     ) -> Result<Actor, Error> {
-        let accepted_actor = requests.fetch::<AcceptedActors>(id.as_str()).await?;
+        let accepted_actor = requests.fetch::<AcceptedActors>(id).await?;
 
         let input_authority = id.authority_components().ok_or(ErrorKind::MissingDomain)?;
         let accepted_actor_id = accepted_actor
diff --git a/src/jobs/contact.rs b/src/jobs/contact.rs
index a98ac8f..3c880af 100644
--- a/src/jobs/contact.rs
+++ b/src/jobs/contact.rs
@@ -42,7 +42,7 @@ impl QueryContact {
 
         let contact = match state
             .requests
-            .fetch::<AcceptedActors>(self.contact_id.as_str())
+            .fetch::<AcceptedActors>(&self.contact_id)
             .await
         {
             Ok(contact) => contact,
diff --git a/src/jobs/deliver.rs b/src/jobs/deliver.rs
index 223608e..72f4aec 100644
--- a/src/jobs/deliver.rs
+++ b/src/jobs/deliver.rs
@@ -35,7 +35,7 @@ impl Deliver {
 
     #[tracing::instrument(name = "Deliver", skip(state))]
     async fn permform(self, state: JobState) -> Result<(), Error> {
-        if let Err(e) = state.requests.deliver(self.to, &self.data).await {
+        if let Err(e) = state.requests.deliver(&self.to, &self.data).await {
             if e.is_breaker() {
                 tracing::debug!("Not trying due to failed breaker");
                 return Ok(());
diff --git a/src/jobs/instance.rs b/src/jobs/instance.rs
index 4713525..59826b5 100644
--- a/src/jobs/instance.rs
+++ b/src/jobs/instance.rs
@@ -41,14 +41,14 @@ impl QueryInstance {
                 let mastodon_instance_uri = iri!(format!("{scheme}://{authority}/api/v1/instance"));
                 state
                     .requests
-                    .fetch_json::<Instance>(mastodon_instance_uri.as_str())
+                    .fetch_json::<Instance>(&mastodon_instance_uri)
                     .await
             }
             InstanceApiType::Misskey => {
                 let msky_meta_uri = iri!(format!("{scheme}://{authority}/api/meta"));
                 state
                     .requests
-                    .fetch_json_msky::<MisskeyMeta>(msky_meta_uri.as_str())
+                    .fetch_json_msky::<MisskeyMeta>(&msky_meta_uri)
                     .await
                     .map(|res| res.into())
             }
diff --git a/src/jobs/nodeinfo.rs b/src/jobs/nodeinfo.rs
index 271b5a1..fa4812f 100644
--- a/src/jobs/nodeinfo.rs
+++ b/src/jobs/nodeinfo.rs
@@ -43,7 +43,7 @@ impl QueryNodeinfo {
 
         let well_known = match state
             .requests
-            .fetch_json::<WellKnown>(well_known_uri.as_str())
+            .fetch_json::<WellKnown>(&well_known_uri)
             .await
         {
             Ok(well_known) => well_known,
@@ -55,7 +55,7 @@ impl QueryNodeinfo {
         };
 
         let href = if let Some(link) = well_known.links.into_iter().find(|l| l.rel.is_supported()) {
-            link.href
+            iri!(&link.href)
         } else {
             return Ok(());
         };
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index 2ae9779..4e1e364 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -67,11 +67,7 @@ impl MyVerify {
 
             actor_id
         } else {
-            match self
-                .0
-                .fetch::<PublicKeyResponse>(public_key_id.as_str())
-                .await
-            {
+            match self.0.fetch::<PublicKeyResponse>(&public_key_id).await {
                 Ok(res) => res.actor_id().ok_or(ErrorKind::MissingId),
                 Err(e) => {
                     if e.is_gone() {
diff --git a/src/requests.rs b/src/requests.rs
index 304d0a6..06c7450 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -229,7 +229,7 @@ impl Requests {
 
         self.reset_err();
 
-        if !res.status().is_success() {
+        if res.status().is_server_error() {
             self.breakers.fail(&parsed_url);
 
             if let Ok(bytes) = res.body().await {
@@ -250,7 +250,7 @@ impl Requests {
     }
 
     #[tracing::instrument(name = "Fetch Json", skip(self), fields(signing_string))]
-    pub(crate) async fn fetch_json<T>(&self, url: &str) -> Result<T, Error>
+    pub(crate) async fn fetch_json<T>(&self, url: &IriString) -> Result<T, Error>
     where
         T: serde::de::DeserializeOwned,
     {
@@ -258,75 +258,40 @@ impl Requests {
     }
 
     #[tracing::instrument(name = "Fetch Json", skip(self), fields(signing_string))]
-    pub(crate) async fn fetch_json_msky<T>(&self, url: &str) -> Result<T, Error>
+    pub(crate) async fn fetch_json_msky<T>(&self, url: &IriString) -> Result<T, Error>
     where
         T: serde::de::DeserializeOwned,
     {
-        self.do_fetch_msky(url, "application/json").await
+        let mut res = self
+            .do_deliver(
+                url,
+                &serde_json::json!({}),
+                "application/json",
+                "application/json",
+            )
+            .await?;
+
+        let body = res
+            .body()
+            .await
+            .map_err(|e| ErrorKind::ReceiveResponse(url.to_string(), e.to_string()))?;
+
+        Ok(serde_json::from_slice(body.as_ref())?)
     }
 
     #[tracing::instrument(name = "Fetch Activity+Json", skip(self), fields(signing_string))]
-    pub(crate) async fn fetch<T>(&self, url: &str) -> Result<T, Error>
+    pub(crate) async fn fetch<T>(&self, url: &IriString) -> Result<T, Error>
     where
         T: serde::de::DeserializeOwned,
     {
         self.do_fetch(url, "application/activity+json").await
     }
 
-    async fn do_fetch<T>(&self, url: &str, accept: &str) -> Result<T, Error>
+    async fn do_fetch<T>(&self, url: &IriString, accept: &str) -> Result<T, Error>
     where
         T: serde::de::DeserializeOwned,
     {
-        self.do_fetch_inner(url, accept, false).await
-    }
-
-    async fn do_fetch_msky<T>(&self, url: &str, accept: &str) -> Result<T, Error>
-    where
-        T: serde::de::DeserializeOwned,
-    {
-        self.do_fetch_inner(url, accept, true).await
-    }
-
-    async fn do_fetch_inner<T>(&self, url: &str, accept: &str, use_post: bool) -> Result<T, Error>
-    where
-        T: serde::de::DeserializeOwned,
-    {
-        let parsed_url = url.parse::<IriString>()?;
-
-        if !self.breakers.should_try(&parsed_url) {
-            return Err(ErrorKind::Breaker.into());
-        }
-
-        let signer = self.signer();
-        let span = tracing::Span::current();
-
-        let client: Client = self.client.borrow().clone();
-        let client_req = match use_post {
-            true => client.post(url),
-            false => client.get(url),
-        };
-        let client_signed = client_req
-            .insert_header(("Accept", accept))
-            .insert_header(Date(SystemTime::now().into()))
-            .signature(
-                self.config.clone(),
-                self.key_id.clone(),
-                move |signing_string| {
-                    span.record("signing_string", signing_string);
-                    span.in_scope(|| signer.sign(signing_string))
-                },
-            )
-            .await?;
-        let res = match use_post {
-            true => {
-                let dummy = serde_json::json!({});
-                client_signed.send_json(&dummy)
-            }
-            false => client_signed.send(),
-        }
-        .await;
-
-        let mut res = self.check_response(&parsed_url, res).await?;
+        let mut res = self.do_fetch_response(url, accept).await?;
 
         let body = res
             .body()
@@ -337,8 +302,16 @@ impl Requests {
     }
 
     #[tracing::instrument(name = "Fetch response", skip(self), fields(signing_string))]
-    pub(crate) async fn fetch_response(&self, url: IriString) -> Result<ClientResponse, Error> {
-        if !self.breakers.should_try(&url) {
+    pub(crate) async fn fetch_response(&self, url: &IriString) -> Result<ClientResponse, Error> {
+        self.do_fetch_response(url, "*/*").await
+    }
+
+    pub(crate) async fn do_fetch_response(
+        &self,
+        url: &IriString,
+        accept: &str,
+    ) -> Result<ClientResponse, Error> {
+        if !self.breakers.should_try(url) {
             return Err(ErrorKind::Breaker.into());
         }
 
@@ -348,7 +321,7 @@ impl Requests {
         let client: Client = self.client.borrow().clone();
         let res = client
             .get(url.as_str())
-            .insert_header(("Accept", "*/*"))
+            .insert_header(("Accept", accept))
             .insert_header(Date(SystemTime::now().into()))
             .no_decompress()
             .signature(
@@ -363,7 +336,7 @@ impl Requests {
             .send()
             .await;
 
-        let res = self.check_response(&url, res).await?;
+        let res = self.check_response(url, res).await?;
 
         Ok(res)
     }
@@ -373,7 +346,27 @@ impl Requests {
         skip_all,
         fields(inbox = inbox.to_string().as_str(), signing_string)
     )]
-    pub(crate) async fn deliver<T>(&self, inbox: IriString, item: &T) -> Result<(), Error>
+    pub(crate) async fn deliver<T>(&self, inbox: &IriString, item: &T) -> Result<(), Error>
+    where
+        T: serde::ser::Serialize + std::fmt::Debug,
+    {
+        self.do_deliver(
+            inbox,
+            item,
+            "application/activity+json",
+            "application/activity+json",
+        )
+        .await?;
+        Ok(())
+    }
+
+    async fn do_deliver<T>(
+        &self,
+        inbox: &IriString,
+        item: &T,
+        content_type: &str,
+        accept: &str,
+    ) -> Result<ClientResponse, Error>
     where
         T: serde::ser::Serialize + std::fmt::Debug,
     {
@@ -388,8 +381,8 @@ impl Requests {
         let client: Client = self.client.borrow().clone();
         let (req, body) = client
             .post(inbox.as_str())
-            .insert_header(("Accept", "application/activity+json"))
-            .insert_header(("Content-Type", "application/activity+json"))
+            .insert_header(("Accept", accept))
+            .insert_header(("Content-Type", content_type))
             .insert_header(Date(SystemTime::now().into()))
             .signature_with_digest(
                 self.config.clone(),
@@ -406,9 +399,9 @@ impl Requests {
 
         let res = req.send_body(body).await;
 
-        self.check_response(&inbox, res).await?;
+        let res = self.check_response(inbox, res).await?;
 
-        Ok(())
+        Ok(res)
     }
 
     fn signer(&self) -> Signer {
diff --git a/src/routes/media.rs b/src/routes/media.rs
index 8a9de62..7cc3ed9 100644
--- a/src/routes/media.rs
+++ b/src/routes/media.rs
@@ -11,7 +11,7 @@ pub(crate) async fn route(
     let uuid = uuid.into_inner();
 
     if let Some(url) = media.get_url(uuid).await? {
-        let res = requests.fetch_response(url).await?;
+        let res = requests.fetch_response(&url).await?;
 
         let mut response = HttpResponse::build(res.status());
 

From 73c016d4180b712011e80eb538c1c48d3b112c32 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 25 Feb 2023 15:04:30 -0600
Subject: [PATCH 68/87] Update deps

---
 Cargo.lock | 365 ++++++++++++++++++++++++++++-------------------------
 1 file changed, 193 insertions(+), 172 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b9c5698..db69830 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -305,9 +305,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.68"
+version = "1.0.69"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61"
+checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
 
 [[package]]
 name = "ap-relay"
@@ -354,7 +354,7 @@ dependencies = [
  "thiserror",
  "time",
  "tokio",
- "toml 0.7.0",
+ "toml 0.7.2",
  "tracing",
  "tracing-actix-web",
  "tracing-awc",
@@ -387,19 +387,20 @@ checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
 
 [[package]]
 name = "async-stream"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dad5c83079eae9969be7fadefe640a1c566901f05ff91ab221de4b6f68d9507e"
+checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e"
 dependencies = [
  "async-stream-impl",
  "futures-core",
+ "pin-project-lite",
 ]
 
 [[package]]
 name = "async-stream-impl"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "10f203db73a71dfa2fb6dd22763990fa26f3d2625a6da2da900d23b87d26be27"
+checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -408,9 +409,9 @@ dependencies = [
 
 [[package]]
 name = "async-trait"
-version = "0.1.63"
+version = "0.1.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff18d764974428cf3a9328e23fc5c986f5fbed46e6cd4cdf42544df5d297ec1"
+checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -459,9 +460,9 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.6.4"
+version = "0.6.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5694b64066a2459918d8074c2ce0d5a88f409431994c2356617c8ae0c4721fc"
+checksum = "2bd379e511536bad07447f899300aa526e9bae8e6f66dc5e5ca45d7587b7c1ec"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -649,9 +650,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
 
 [[package]]
 name = "bytes"
-version = "1.3.0"
+version = "1.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c"
+checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
 [[package]]
 name = "bytestring"
@@ -696,9 +697,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.1.4"
+version = "4.1.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f13b9c79b5d1dd500d20ef541215a6423c75829ef43117e1b4d17fd8af0b5d76"
+checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
 dependencies = [
  "bitflags",
  "clap_derive",
@@ -724,9 +725,9 @@ dependencies = [
 
 [[package]]
 name = "clap_lex"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "783fe232adfca04f90f56201b26d79682d4cd2625e0bc7290b95123afe558ade"
+checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09"
 dependencies = [
  "os_str_bytes",
 ]
@@ -914,7 +915,7 @@ dependencies = [
  "hashbrown 0.12.3",
  "lock_api",
  "once_cell",
- "parking_lot_core 0.9.6",
+ "parking_lot_core 0.9.7",
 ]
 
 [[package]]
@@ -981,9 +982,9 @@ checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
 name = "encoding_rs"
-version = "0.8.31"
+version = "0.8.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b"
+checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394"
 dependencies = [
  "cfg-if",
 ]
@@ -1033,9 +1034,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
 
 [[package]]
 name = "fastrand"
-version = "1.8.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be"
 dependencies = [
  "instant",
 ]
@@ -1093,9 +1094,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0"
+checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1108,9 +1109,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "52ba265a92256105f45b719605a571ffe2d1f0fea3807304b522c1d778f79eed"
+checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -1118,15 +1119,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac"
+checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2"
+checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -1135,15 +1136,15 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "00f5fb52a06bdcadeb54e8d3671f8888a39697dcb0b81b23b55174030427f4eb"
+checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bdfb8ce053d86b91919aad980c220b1fb8401a9394410e1c289ed7e66b61835d"
+checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -1152,21 +1153,21 @@ dependencies = [
 
 [[package]]
 name = "futures-sink"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39c15cf1a4aa79df40f1bb462fb39676d0ad9e366c2a33b590d7c66f4f81fcf9"
+checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
 
 [[package]]
 name = "futures-task"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ffb393ac5d9a6eaa9d3fdf37ae2776656b706e200c8e16b1bdb227f5198e6ea"
+checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
 
 [[package]]
 name = "futures-util"
-version = "0.3.25"
+version = "0.3.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "197676987abd2f9cadff84926f410af1c183608d36641465df73ae8211dc65d6"
+checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1262,9 +1263,9 @@ dependencies = [
 
 [[package]]
 name = "heck"
-version = "0.4.0"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
+checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
@@ -1275,6 +1276,12 @@ dependencies = [
  "libc",
 ]
 
+[[package]]
+name = "hermit-abi"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286"
+
 [[package]]
 name = "html5ever"
 version = "0.26.0"
@@ -1291,9 +1298,9 @@ dependencies = [
 
 [[package]]
 name = "http"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
+checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
 dependencies = [
  "bytes",
  "fnv",
@@ -1367,9 +1374,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "hyper"
-version = "0.14.23"
+version = "0.14.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
+checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -1460,12 +1467,12 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.4"
+version = "1.0.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7d6c6f8c91b4b9ed43484ad1a938e393caf35960fce7f82a040497207bd8e9e"
+checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
 dependencies = [
  "libc",
- "windows-sys",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -1486,14 +1493,14 @@ dependencies = [
 
 [[package]]
 name = "is-terminal"
-version = "0.4.2"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28dfb6c8100ccc63462345b67d1bbc3679177c75ee4bf59bf29c8b1d110b8189"
+checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.3.1",
  "io-lifetimes",
  "rustix",
- "windows-sys",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -1522,9 +1529,9 @@ checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
 
 [[package]]
 name = "js-sys"
-version = "0.3.60"
+version = "0.3.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49409df3e3bf0856b916e2ceaca09ee28e6871cf7d9ce97a692cacfdb2a25a47"
+checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -1775,9 +1782,9 @@ dependencies = [
 
 [[package]]
 name = "minify-html"
-version = "0.10.7"
+version = "0.10.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d2d0e6da317b10501ed44ebe2aa59c3926890a6dd2a0a77d069e5e9ea69b5c0"
+checksum = "7754d4669873379ea6a8a5b56e406eb83de713af8a791517ef35a0c832b1e7d5"
 dependencies = [
  "aho-corasick",
  "css-minify",
@@ -1789,9 +1796,9 @@ dependencies = [
 
 [[package]]
 name = "minify-js"
-version = "0.4.2"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58a1566cb31504e32f009f6c47ad83f7eeb91d00e8e9845314f1d0b2202ef595"
+checksum = "c300f90ba1138b5c5daf5d9441dc9bdc67b808aac22cf638362a2647bc213be4"
 dependencies = [
  "lazy_static",
  "parse-js",
@@ -1814,14 +1821,14 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.8.5"
+version = "0.8.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5d732bc30207a6423068df043e3d02e0735b155ad7ce1a6f76fe2baa5b158de"
+checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
 dependencies = [
  "libc",
  "log",
  "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -1861,15 +1868,6 @@ dependencies = [
  "minimal-lexical",
 ]
 
-[[package]]
-name = "nom8"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae01545c9c7fc4486ab7debaf2aad7003ac19431791868fb2e8066df97fad2f8"
-dependencies = [
- "memchr",
-]
-
 [[package]]
 name = "nu-ansi-term"
 version = "0.46.0"
@@ -1958,15 +1956,15 @@ version = "1.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b"
 dependencies = [
- "hermit-abi",
+ "hermit-abi 0.2.6",
  "libc",
 ]
 
 [[package]]
 name = "once_cell"
-version = "1.17.0"
+version = "1.17.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66"
+checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "opentelemetry"
@@ -2097,7 +2095,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.6",
+ "parking_lot_core 0.9.7",
 ]
 
 [[package]]
@@ -2116,15 +2114,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.6"
+version = "0.9.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf"
+checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-sys",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -2167,9 +2165,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.5.4"
+version = "2.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ab62d2fa33726dbe6321cc97ef96d8cde531e3eeaf858a058de53a8a6d40d8f"
+checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2177,9 +2175,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.4"
+version = "2.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bf026e2d0581559db66d837fe5242320f525d85c76283c61f4d51a1238d65ea"
+checksum = "2ac3922aac69a40733080f53c1ce7f91dcf57e1a5f6c52f421fadec7fbdc4b69"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2187,9 +2185,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.4"
+version = "2.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b27bd18aa01d91c8ed2b61ea23406a676b42d82609c6e2581fba42f0c15f17f"
+checksum = "d06646e185566b5961b4058dd107e0a7f56e77c3f484549fb119867773c0f202"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2200,9 +2198,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.5.4"
+version = "2.5.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f02b677c1859756359fc9983c2e56a0237f18624a3789528804406b7e915e5d"
+checksum = "e6f60b2ba541577e2a0c307c8f39d1439108120eb7903adeb6497fa880c59616"
 dependencies = [
  "once_cell",
  "pest",
@@ -2211,9 +2209,9 @@ dependencies = [
 
 [[package]]
 name = "petgraph"
-version = "0.6.2"
+version = "0.6.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6d5014253a1331579ce62aa67443b4a658c5e7dd03d4bc6d302b94474888143"
+checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
 dependencies = [
  "fixedbitset",
  "indexmap",
@@ -2365,18 +2363,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.50"
+version = "1.0.51"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ef7d57beacfaf2d8aee5937dab7b7f28de3cb8b1828479bb5de2a7106f2bae2"
+checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.11.6"
+version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21dc42e00223fc37204bd4aa177e69420c604ca4a183209a8f9de30c6d934698"
+checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
 dependencies = [
  "bytes",
  "prost-derive",
@@ -2384,9 +2382,9 @@ dependencies = [
 
 [[package]]
 name = "prost-build"
-version = "0.11.6"
+version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a3f8ad728fb08fe212df3c05169e940fbb6d9d16a877ddde14644a983ba2012e"
+checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12"
 dependencies = [
  "bytes",
  "heck",
@@ -2406,9 +2404,9 @@ dependencies = [
 
 [[package]]
 name = "prost-derive"
-version = "0.11.6"
+version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8bda8c0881ea9f722eb9629376db3d0b903b462477c1aafcb0566610ac28ac5d"
+checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
@@ -2419,11 +2417,10 @@ dependencies = [
 
 [[package]]
 name = "prost-types"
-version = "0.11.6"
+version = "0.11.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5e0526209433e96d83d750dd81a99118edbc55739e7e61a46764fd2ad537788"
+checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88"
 dependencies = [
- "bytes",
  "prost",
 ]
 
@@ -2494,9 +2491,9 @@ dependencies = [
 
 [[package]]
 name = "raw-cpuid"
-version = "10.6.0"
+version = "10.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6823ea29436221176fe662da99998ad3b4db2c7f31e7b6f5fe43adccd6320bb"
+checksum = "c307f7aacdbab3f0adee67d52739a1d71112cc068d6fab169ddeb18e48877fad"
 dependencies = [
  "bitflags",
 ]
@@ -2545,15 +2542,6 @@ version = "0.6.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
 
-[[package]]
-name = "remove_dir_all"
-version = "0.5.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "reqwest"
 version = "0.11.14"
@@ -2714,16 +2702,16 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.7"
+version = "0.36.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d4fdebc4b395b7fbb9ab11e462e20ed9051e7b16e42d24042c776eca0ac81b03"
+checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
 dependencies = [
  "bitflags",
  "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys",
- "windows-sys",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -2803,9 +2791,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.91"
+version = "1.0.93"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883"
+checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
 dependencies = [
  "itoa",
  "ryu",
@@ -2814,9 +2802,9 @@ dependencies = [
 
 [[package]]
 name = "serde_spanned"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c68e921cef53841b8925c2abadd27c9b891d9613bdc43d6b823062866df38e8"
+checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
 dependencies = [
  "serde",
 ]
@@ -2878,9 +2866,9 @@ dependencies = [
 
 [[package]]
 name = "signal-hook-registry"
-version = "1.4.0"
+version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
+checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
 dependencies = [
  "libc",
 ]
@@ -2909,9 +2897,9 @@ checksum = "ceb945e54128e09c43d8e4f1277851bd5044c6fc540bbaa2ad888f60b3da9ae7"
 
 [[package]]
 name = "slab"
-version = "0.4.7"
+version = "0.4.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
+checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d"
 dependencies = [
  "autocfg",
 ]
@@ -3004,9 +2992,9 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
 
 [[package]]
 name = "syn"
-version = "1.0.107"
+version = "1.0.109"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3015,9 +3003,9 @@ dependencies = [
 
 [[package]]
 name = "sync_wrapper"
-version = "0.1.1"
+version = "0.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20518fe4a4c9acf048008599e464deb21beeae3d3578418951a189c235a7a9a8"
+checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
 
 [[package]]
 name = "take_mut"
@@ -3033,9 +3021,9 @@ checksum = "20f34339676cdcab560c9a82300c4c2581f68b9369aedf0fae86f2ff9565ff3e"
 
 [[package]]
 name = "teloxide"
-version = "0.12.0"
+version = "0.12.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0b08789da4f24d049aea06e17c1c7b92c1b92222115e357014a46e842fb8c84"
+checksum = "c63345cf32a8850ebddcdd769dc2d5193d5e231262d5dada264b79da01a664da"
 dependencies = [
  "aquamarine",
  "bytes",
@@ -3059,9 +3047,9 @@ dependencies = [
 
 [[package]]
 name = "teloxide-core"
-version = "0.9.0"
+version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25d05d54e4c83825f143da24f0fe35c1171b634f3ba1f6c9e2fae6d98e2446b6"
+checksum = "303db260110c238e3af77bb9dff18bf7a5b5196f783059b0852aab75f91d5a16"
 dependencies = [
  "bitflags",
  "bytes",
@@ -3102,16 +3090,15 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.3.0"
+version = "3.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
+checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
 dependencies = [
  "cfg-if",
  "fastrand",
- "libc",
  "redox_syscall",
- "remove_dir_all",
- "winapi",
+ "rustix",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -3156,18 +3143,19 @@ dependencies = [
 
 [[package]]
 name = "thread_local"
-version = "1.1.4"
+version = "1.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180"
+checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152"
 dependencies = [
+ "cfg-if",
  "once_cell",
 ]
 
 [[package]]
 name = "time"
-version = "0.3.17"
+version = "0.3.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
+checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
 dependencies = [
  "itoa",
  "serde",
@@ -3183,9 +3171,9 @@ checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
 
 [[package]]
 name = "time-macros"
-version = "0.2.6"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d967f99f534ca7e495c575c62638eebc2898a8c84c119b89e250477bc4ba16b2"
+checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
 dependencies = [
  "time-core",
 ]
@@ -3201,15 +3189,15 @@ dependencies = [
 
 [[package]]
 name = "tinyvec_macros"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
+checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.24.2"
+version = "1.25.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a12a59981d9e3c38d216785b0c37399f6e415e8d0712047620f189371b0bb"
+checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3222,7 +3210,7 @@ dependencies = [
  "socket2",
  "tokio-macros",
  "tracing",
- "windows-sys",
+ "windows-sys 0.42.0",
 ]
 
 [[package]]
@@ -3259,9 +3247,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.11"
+version = "0.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d660770404473ccd7bc9f8b28494a811bc18542b915c0855c51e8f419d5223ce"
+checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -3270,9 +3258,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-util"
-version = "0.7.4"
+version = "0.7.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bb2e075f03b3d66d8d8785356224ba688d2906a371015e225beeb65ca92c740"
+checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
 dependencies = [
  "bytes",
  "futures-core",
@@ -3293,9 +3281,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.7.0"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f560bc7fb3eb31f5eee1340c68a2160cad39605b7b9c9ec32045ddbdee13b85"
+checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -3305,24 +3293,24 @@ dependencies = [
 
 [[package]]
 name = "toml_datetime"
-version = "0.6.0"
+version = "0.6.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "886f31a9b85b6182cabd4d8b07df3b451afcc216563748201490940d2a28ed36"
+checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "toml_edit"
-version = "0.19.0"
+version = "0.19.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233d8716cdc5d20ec88a18a839edaf545edc71efa4a5ff700ef4a102c26cd8fa"
+checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
 dependencies = [
  "indexmap",
- "nom8",
  "serde",
  "serde_spanned",
  "toml_datetime",
+ "winnow",
 ]
 
 [[package]]
@@ -3619,9 +3607,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
 [[package]]
 name = "uuid"
-version = "1.2.2"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "422ee0de9031b5b948b97a8fc04e3aa35230001a722ddd27943e0be31564ce4c"
+checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
 dependencies = [
  "getrandom",
  "serde",
@@ -3663,9 +3651,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268"
+checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -3673,9 +3661,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142"
+checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
 dependencies = [
  "bumpalo",
  "log",
@@ -3688,9 +3676,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.33"
+version = "0.4.34"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23639446165ca5a5de86ae1d8896b737ae80319560fbaa4c2887b7da6e7ebd7d"
+checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -3700,9 +3688,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810"
+checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -3710,9 +3698,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c"
+checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3723,9 +3711,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.83"
+version = "0.2.84"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f"
+checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
 
 [[package]]
 name = "wasm-streams"
@@ -3742,9 +3730,9 @@ dependencies = [
 
 [[package]]
 name = "web-sys"
-version = "0.3.60"
+version = "0.3.61"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcda906d8be16e728fd5adc5b729afad4e444e106ab28cd1c7256e54fa61510f"
+checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -3826,6 +3814,30 @@ dependencies = [
  "windows_x86_64_msvc",
 ]
 
+[[package]]
+name = "windows-sys"
+version = "0.45.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
+dependencies = [
+ "windows-targets",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.42.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+dependencies = [
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
+]
+
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.42.1"
@@ -3868,6 +3880,15 @@ version = "0.42.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
 
+[[package]]
+name = "winnow"
+version = "0.3.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "winreg"
 version = "0.10.1"

From ae91aa8fa72a2ba54a1c46640e83f886dd6d971b Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 25 Feb 2023 15:06:18 -0600
Subject: [PATCH 69/87] Update bcrypt

---
 Cargo.lock | 7 ++++---
 Cargo.toml | 2 +-
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index db69830..813c964 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -574,13 +574,14 @@ checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
 
 [[package]]
 name = "bcrypt"
-version = "0.13.0"
+version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7e7c93a3fb23b2fdde989b2c9ec4dd153063ec81f408507f84c090cd91c6641"
+checksum = "9df288bec72232f78c1ec5fe4e8f1d108aa0265476e93097593c803c8c02062a"
 dependencies = [
- "base64 0.13.1",
+ "base64 0.21.0",
  "blowfish",
  "getrandom",
+ "subtle",
  "zeroize",
 ]
 
diff --git a/Cargo.toml b/Cargo.toml
index 581f00a..7f224b1 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,7 +33,7 @@ activitystreams = "0.7.0-alpha.21"
 activitystreams-ext = "0.1.0-alpha.3"
 ammonia = "3.1.0"
 awc = { version = "3.0.0", default-features = false, features = ["rustls"] }
-bcrypt = "0.13"
+bcrypt = "0.14"
 base64 = "0.21"
 clap = { version = "4.0.0", features = ["derive"] }
 config = "0.13.0"

From d644e8373315d0eef7cc1b5336cf221a871115e8 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 25 Feb 2023 15:14:24 -0600
Subject: [PATCH 70/87] Bump version

---
 Cargo.lock | 2 +-
 Cargo.toml | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 813c964..ae8eadc 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -311,7 +311,7 @@ checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.81"
+version = "0.3.82"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 7f224b1..79dcc41 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.81"
+version = "0.3.82"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"

From afd4105d0f43d3fdce16eb8ef97c6cde9ebf086d Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 23 Mar 2023 13:51:23 -0500
Subject: [PATCH 71/87] Add flake

---
 .gitignore |   3 +
 Cargo.lock | 440 ++++++++++++++++++++++++++---------------------------
 Cargo.toml |   2 +-
 flake.lock |  43 ++++++
 flake.nix  |  34 +++++
 relay.nix  |  27 ++++
 6 files changed, 324 insertions(+), 225 deletions(-)
 create mode 100644 flake.lock
 create mode 100644 flake.nix
 create mode 100644 relay.nix

diff --git a/.gitignore b/.gitignore
index 1ce4608..447738f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,6 @@
 /target
 /artifacts
 /sled
+/.direnv
+/.envrc
+/result
diff --git a/Cargo.lock b/Cargo.lock
index ae8eadc..795a5f7 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -43,7 +43,7 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "bytes",
  "futures-core",
  "futures-sink",
@@ -56,18 +56,18 @@ dependencies = [
 
 [[package]]
 name = "actix-http"
-version = "3.3.0"
+version = "3.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0070905b2c4a98d184c4e81025253cb192aa8a73827553f38e9410801ceb35bb"
+checksum = "c2079246596c18b4a33e274ae10c0e50613f4d32a4198e09c7b93771013fed74"
 dependencies = [
  "actix-codec",
  "actix-rt",
  "actix-service",
  "actix-tls",
  "actix-utils",
- "ahash 0.7.6",
+ "ahash 0.8.3",
  "base64 0.21.0",
- "bitflags",
+ "bitflags 1.3.2",
  "brotli",
  "bytes",
  "bytestring",
@@ -100,7 +100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "465a6172cf69b960917811022d8f29bc0b7fa1398bc4f78b3c466673db1213b6"
 dependencies = [
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -187,9 +187,9 @@ dependencies = [
 
 [[package]]
 name = "actix-web"
-version = "4.3.0"
+version = "4.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "464e0fddc668ede5f26ec1f9557a8d44eda948732f40c6b0ad79126930eb775f"
+checksum = "cd3cb42f9566ab176e1ef0b8b3a896529062b4efc6be0123046095914c4c1c96"
 dependencies = [
  "actix-codec",
  "actix-http",
@@ -262,6 +262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2c99f64d1e06488f620f932677e24bc6e2897582980441ae90a671415bd7ec2f"
 dependencies = [
  "cfg-if",
+ "getrandom",
  "once_cell",
  "version_check",
 ]
@@ -305,9 +306,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.69"
+version = "1.0.70"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800"
+checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
 
 [[package]]
 name = "ap-relay"
@@ -354,7 +355,7 @@ dependencies = [
  "thiserror",
  "time",
  "tokio",
- "toml 0.7.2",
+ "toml 0.7.3",
  "tracing",
  "tracing-actix-web",
  "tracing-awc",
@@ -376,7 +377,7 @@ dependencies = [
  "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -404,18 +405,18 @@ checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "async-trait"
-version = "0.1.64"
+version = "0.1.67"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cd7fce9ba8c3c042128ce72d8b2ddbf3a05747efb67ea0313c635e10bda47a2"
+checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -426,9 +427,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
 
 [[package]]
 name = "awc"
-version = "3.1.0"
+version = "3.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dff3fc64a176e0d4398c71b0f2c2679ff4a723c6ed8fcc68dfe5baa00665388"
+checksum = "87ef547a81796eb2dfe9b345aba34c2e08391a0502493711395b36dd64052b69"
 dependencies = [
  "actix-codec",
  "actix-http",
@@ -460,13 +461,13 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.6.8"
+version = "0.6.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2bd379e511536bad07447f899300aa526e9bae8e6f66dc5e5ca45d7587b7c1ec"
+checksum = "349f8ccfd9221ee7d1f3d4b33e1f8319b3a81ed8f61f2ea40b37b859794b4491"
 dependencies = [
  "async-trait",
  "axum-core",
- "bitflags",
+ "bitflags 1.3.2",
  "bytes",
  "futures-util",
  "http",
@@ -482,16 +483,15 @@ dependencies = [
  "serde",
  "sync_wrapper",
  "tower",
- "tower-http",
  "tower-layer",
  "tower-service",
 ]
 
 [[package]]
 name = "axum-core"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cae3e661676ffbacb30f1a824089a8c9150e71017f7e1e38f2aa32009188d34"
+checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e"
 dependencies = [
  "async-trait",
  "bytes",
@@ -506,9 +506,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs"
-version = "0.14.0"
+version = "0.14.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62dc7cfc967d6714768097a876ca2941a54a26976c6d3c95ea6da48974890970"
+checksum = "e7d6695c1cc80d11c6a48974c57289b020a24426cad4284c329374f114997a8a"
 dependencies = [
  "background-jobs-actix",
  "background-jobs-core",
@@ -568,9 +568,9 @@ checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
 
 [[package]]
 name = "base64ct"
-version = "1.5.3"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b645a089122eccb6111b4f81cbc1a49f5900ac4666bb93ac027feaecf15607bf"
+checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
 
 [[package]]
 name = "bcrypt"
@@ -592,10 +592,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
 [[package]]
-name = "block-buffer"
-version = "0.10.3"
+name = "bitflags"
+version = "2.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e"
+checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
+
+[[package]]
+name = "block-buffer"
+version = "0.10.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
 dependencies = [
  "generic-array",
 ]
@@ -657,9 +663,9 @@ checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
 
 [[package]]
 name = "bytestring"
-version = "1.2.0"
+version = "1.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7f83e57d9154148e355404702e2694463241880b939570d7c97c014da7a69a1"
+checksum = "238e4886760d98c4f899360c834fa93e62cf7f721ac3c2da375cbdf4b8679aae"
 dependencies = [
  "bytes",
 ]
@@ -678,9 +684,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.23"
+version = "0.4.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16b0a3d9ed01224b22057780a37bb8c5dbfe1be8ba48678e7bf57ec4b385411f"
+checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
 dependencies = [
  "num-integer",
  "num-traits",
@@ -688,9 +694,9 @@ dependencies = [
 
 [[package]]
 name = "cipher"
-version = "0.4.3"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1873270f8f7942c191139cb8a40fd228da6c3fd2fc376d7e92d47aa14aeb59e"
+checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
 dependencies = [
  "crypto-common",
  "inout",
@@ -698,11 +704,11 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.1.6"
+version = "4.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec0b0588d44d4d63a87dbd75c136c166bbfd9a86a31cb89e09906521c7d3f5e3"
+checksum = "76e21918af71fb4bcd813230cf549e33d14f73d0326b932b630ce2930332b131"
 dependencies = [
- "bitflags",
+ "bitflags 2.0.2",
  "clap_derive",
  "clap_lex",
  "is-terminal",
@@ -713,22 +719,21 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.1.0"
+version = "4.1.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "684a277d672e91966334af371f1a7b5833f9aa00b07c84e92fbce95e00208ce8"
+checksum = "9a932373bab67b984c790ddf2c9ca295d8e3af3b7ef92de5a5bacdccdee4b09b"
 dependencies = [
  "heck",
- "proc-macro-error",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.8",
 ]
 
 [[package]]
 name = "clap_lex"
-version = "0.3.2"
+version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09"
+checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
 dependencies = [
  "os_str_bytes",
 ]
@@ -790,9 +795,9 @@ dependencies = [
 
 [[package]]
 name = "const-oid"
-version = "0.9.1"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cec318a675afcb6a1ea1d4340e2d377e56e47c266f28043ceccbf4412ddfdd3b"
+checksum = "520fbf3c07483f94e3e3ca9d0cfd913d7718ef2483d2cfd91c0d9e91474ab913"
 
 [[package]]
 name = "convert_case"
@@ -820,9 +825,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.6"
+version = "0.5.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
+checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
 dependencies = [
  "cfg-if",
  "crossbeam-utils",
@@ -830,9 +835,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.13"
+version = "0.9.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01a9af1f4c2ef74bb8aa1f7e19706bc72d03598c8a570bb5de72243c7a9d9d5a"
+checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
 dependencies = [
  "autocfg",
  "cfg-if",
@@ -843,9 +848,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.14"
+version = "0.8.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4fb766fa798726286dbbb842f174001dab8abc7b627a1dd86e0b7222a95d929f"
+checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
 dependencies = [
  "cfg-if",
 ]
@@ -892,7 +897,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -903,7 +908,7 @@ checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835"
 dependencies = [
  "darling_core",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -940,7 +945,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "rustc_version",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1095,9 +1100,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13e2792b0ff0340399d58445b88fd9770e3489eff258a4cbc1523418f12abf84"
+checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1110,9 +1115,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e5317663a9089767a1ec00a487df42e0ca174b61b4483213ac24448e4664df5"
+checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -1120,15 +1125,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec90ff4d0fe1f57d600049061dc6bb68ed03c7d2fbd697274c41805dcb3f8608"
+checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8de0a35a6ab97ec8869e32a2473f4b1324459e14c29275d14b10cb1fd19b50e"
+checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -1137,38 +1142,38 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bfb8371b6fb2aeb2d280374607aeabfc99d95c72edfe51692e42d3d7f0d08531"
+checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95a73af87da33b5acf53acfebdc339fe592ecf5357ac7c0a7734ab9d8c876a70"
+checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f310820bb3e8cfd46c80db4d7fb8353e15dfff853a127158425f31e0be6c8364"
+checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
 
 [[package]]
 name = "futures-task"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcf79a1bf610b10f42aea489289c5a2c478a786509693b80cd39c44ccd936366"
+checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
 
 [[package]]
 name = "futures-util"
-version = "0.3.26"
+version = "0.3.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c1d6de3acfef38d2be4b1f543f553131788603495be83da675e180c8d6b7bd1"
+checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1214,9 +1219,9 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.3.15"
+version = "0.3.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f9f29bc9dda355256b2916cf526ab02ce0aeaaaf2bad60d65ef3f12f11dd0f4"
+checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
 dependencies = [
  "bytes",
  "fnv",
@@ -1294,7 +1299,7 @@ dependencies = [
  "markup5ever",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1319,12 +1324,6 @@ dependencies = [
  "pin-project-lite",
 ]
 
-[[package]]
-name = "http-range-header"
-version = "0.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
-
 [[package]]
 name = "http-signature-normalization"
 version = "0.7.0"
@@ -1375,9 +1374,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "hyper"
-version = "0.14.24"
+version = "0.14.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e011372fa0b68db8350aa7a248930ecc7839bf46d8485577d69f117a75f164c"
+checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -1468,10 +1467,11 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.5"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1abeb7a0dd0f8181267ff8adc397075586500b81b28a73e8a0208b00fc170fb3"
+checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
 dependencies = [
+ "hermit-abi 0.3.1",
  "libc",
  "windows-sys 0.45.0",
 ]
@@ -1494,9 +1494,9 @@ dependencies = [
 
 [[package]]
 name = "is-terminal"
-version = "0.4.4"
+version = "0.4.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857"
+checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e"
 dependencies = [
  "hermit-abi 0.3.1",
  "io-lifetimes",
@@ -1524,9 +1524,9 @@ dependencies = [
 
 [[package]]
 name = "itoa"
-version = "1.0.5"
+version = "1.0.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fad582f4b9e86b6caa621cabeb0963332d92eea04729ab12892c2533951e6440"
+checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "js-sys"
@@ -1565,9 +1565,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.139"
+version = "0.2.140"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79"
+checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
 
 [[package]]
 name = "libm"
@@ -1626,9 +1626,9 @@ dependencies = [
 
 [[package]]
 name = "lru"
-version = "0.9.0"
+version = "0.10.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71e7d46de488603ffdd5f30afbc64fbba2378214a2c3a2fb83abf3d33126df17"
+checksum = "03f1160296536f10c833a82dca22267d5486734230d47bf00bf435885814ba1e"
 dependencies = [
  "hashbrown 0.13.2",
 ]
@@ -1697,9 +1697,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
 name = "memoffset"
-version = "0.7.1"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4"
+checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
 dependencies = [
  "autocfg",
 ]
@@ -1741,7 +1741,7 @@ checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -1767,9 +1767,9 @@ dependencies = [
 
 [[package]]
 name = "mime"
-version = "0.3.16"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d"
+checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
 
 [[package]]
 name = "mime_guess"
@@ -2068,9 +2068,9 @@ dependencies = [
 
 [[package]]
 name = "os_str_bytes"
-version = "6.4.1"
+version = "6.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee"
+checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
 
 [[package]]
 name = "overload"
@@ -2139,9 +2139,9 @@ dependencies = [
 
 [[package]]
 name = "paste"
-version = "1.0.11"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d01a5bd0424d00070b0098dd17ebca6f961a959dead1dbcbbbc1d1cd8d3deeba"
+checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79"
 
 [[package]]
 name = "pathdiff"
@@ -2166,9 +2166,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.5.5"
+version = "2.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "028accff104c4e513bad663bbcd2ad7cfd5304144404c31ed0a77ac103d00660"
+checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2176,9 +2176,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.5"
+version = "2.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2ac3922aac69a40733080f53c1ce7f91dcf57e1a5f6c52f421fadec7fbdc4b69"
+checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2186,22 +2186,22 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.5"
+version = "2.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d06646e185566b5961b4058dd107e0a7f56e77c3f484549fb119867773c0f202"
+checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b"
 dependencies = [
  "pest",
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
 name = "pest_meta"
-version = "2.5.5"
+version = "2.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e6f60b2ba541577e2a0c307c8f39d1439108120eb7903adeb6497fa880c59616"
+checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80"
 dependencies = [
  "once_cell",
  "pest",
@@ -2273,7 +2273,7 @@ checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2330,12 +2330,12 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
 [[package]]
 name = "prettyplease"
-version = "0.1.23"
+version = "0.1.25"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e97e3215779627f01ee256d2fad52f3d95e8e1c11e9fc6fd08f7cd455d5d5c78"
+checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
 dependencies = [
  "proc-macro2",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2347,7 +2347,7 @@ dependencies = [
  "proc-macro-error-attr",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "version_check",
 ]
 
@@ -2364,9 +2364,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.51"
+version = "1.0.53"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5d727cae5b39d21da60fa540906919ad737832fe0b1c165da3a34d6548c849d6"
+checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
 dependencies = [
  "unicode-ident",
 ]
@@ -2398,7 +2398,7 @@ dependencies = [
  "prost",
  "prost-types",
  "regex",
- "syn",
+ "syn 1.0.109",
  "tempfile",
  "which",
 ]
@@ -2413,7 +2413,7 @@ dependencies = [
  "itertools 0.10.5",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2443,9 +2443,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.23"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
 dependencies = [
  "proc-macro2",
 ]
@@ -2492,11 +2492,11 @@ dependencies = [
 
 [[package]]
 name = "raw-cpuid"
-version = "10.6.1"
+version = "10.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c307f7aacdbab3f0adee67d52739a1d71112cc068d6fab169ddeb18e48877fad"
+checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
 ]
 
 [[package]]
@@ -2514,14 +2514,14 @@ version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
 ]
 
 [[package]]
 name = "regex"
-version = "1.7.1"
+version = "1.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48aaa5748ba571fb95cd2c85c09f629215d3a6ece942baa100950af03a34f733"
+checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
 dependencies = [
  "aho-corasick",
  "memchr",
@@ -2539,15 +2539,15 @@ dependencies = [
 
 [[package]]
 name = "regex-syntax"
-version = "0.6.28"
+version = "0.6.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "456c603be3e8d448b072f410900c09faf164fbce2d480456f50eea6e25f9c848"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "reqwest"
-version = "0.11.14"
+version = "0.11.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21eed90ec8570952d53b772ecf8f206aa1ec9a3d76b2521c56c42973f2d91ee9"
+checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949"
 dependencies = [
  "base64 0.21.0",
  "bytes",
@@ -2607,15 +2607,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
 dependencies = [
  "base64 0.13.1",
- "bitflags",
+ "bitflags 1.3.2",
  "serde",
 ]
 
 [[package]]
 name = "rsa"
-version = "0.8.1"
+version = "0.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89b3896c9b7790b70a9aa314a30e4ae114200992a19c96cbe0ca6070edd32ab8"
+checksum = "55a77d189da1fee555ad95b7e50e7457d91c0e089ec68ca69ad2989413bbdab4"
 dependencies = [
  "byteorder",
  "digest",
@@ -2703,11 +2703,11 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.8"
+version = "0.36.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f43abb88211988493c1abb44a70efa56ff0ce98f233b7b276146f1f3f7ba9644"
+checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "errno",
  "io-lifetimes",
  "libc",
@@ -2738,15 +2738,15 @@ dependencies = [
 
 [[package]]
 name = "rustversion"
-version = "1.0.11"
+version = "1.0.12"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5583e89e108996506031660fe09baa5011b9dd0341b89029313006d1fb508d70"
+checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06"
 
 [[package]]
 name = "ryu"
-version = "1.0.12"
+version = "1.0.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde"
+checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
 
 [[package]]
 name = "scopeguard"
@@ -2766,35 +2766,35 @@ dependencies = [
 
 [[package]]
 name = "semver"
-version = "1.0.16"
+version = "1.0.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "58bc9567378fc7690d6b2addae4e60ac2eeea07becb2c64b9f218b53865cba2a"
+checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 
 [[package]]
 name = "serde"
-version = "1.0.152"
+version = "1.0.158"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb7d1f0d3021d347a83e556fc4683dea2ea09d87bccdf88ff5c12545d89d5efb"
+checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.158"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.8",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.93"
+version = "1.0.94"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cad406b69c91885b5107daf2c29572f6c8cdb3c66826821e286c533490c0bc76"
+checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
 dependencies = [
  "itoa",
  "ryu",
@@ -2831,7 +2831,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -2929,9 +2929,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0"
 
 [[package]]
 name = "socket2"
-version = "0.4.7"
+version = "0.4.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
+checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662"
 dependencies = [
  "libc",
  "winapi",
@@ -2955,9 +2955,9 @@ dependencies = [
 
 [[package]]
 name = "string_cache"
-version = "0.8.4"
+version = "0.8.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
+checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b"
 dependencies = [
  "new_debug_unreachable",
  "once_cell",
@@ -2987,9 +2987,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
 
 [[package]]
 name = "subtle"
-version = "2.4.1"
+version = "2.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
+checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
 
 [[package]]
 name = "syn"
@@ -3002,6 +3002,17 @@ dependencies = [
  "unicode-ident",
 ]
 
+[[package]]
+name = "syn"
+version = "2.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
 [[package]]
 name = "sync_wrapper"
 version = "0.1.2"
@@ -3052,7 +3063,7 @@ version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "303db260110c238e3af77bb9dff18bf7a5b5196f783059b0852aab75f91d5a16"
 dependencies = [
- "bitflags",
+ "bitflags 1.3.2",
  "bytes",
  "chrono",
  "derive_more",
@@ -3086,7 +3097,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3124,22 +3135,22 @@ dependencies = [
 
 [[package]]
 name = "thiserror"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a9cd18aa97d5c45c6603caea1da6628790b37f7a34b6ca89522331c5180fed0"
+checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
 dependencies = [
  "thiserror-impl",
 ]
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.38"
+version = "1.0.40"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fb327af4685e4d03fa8cbcf1716380da910eeb2bb8be417e7f9fd3fb164f36f"
+checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 2.0.8",
 ]
 
 [[package]]
@@ -3196,9 +3207,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.25.0"
+version = "1.26.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c8e00990ebabbe4c14c08aca901caed183ecd5c09562a12c824bb53d3c3fd3af"
+checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3211,7 +3222,7 @@ dependencies = [
  "socket2",
  "tokio-macros",
  "tracing",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -3232,7 +3243,7 @@ checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3282,9 +3293,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7afcae9e3f0fe2c370fd4657108972cbb2fa9db1b9f84849cefd80741b01cb6"
+checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -3303,9 +3314,9 @@ dependencies = [
 
 [[package]]
 name = "toml_edit"
-version = "0.19.4"
+version = "0.19.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a1eb0622d28f4b9c90adc4ea4b2b46b47663fde9ac5fafcb14a1369d5508825"
+checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
 dependencies = [
  "indexmap",
  "serde",
@@ -3356,7 +3367,7 @@ dependencies = [
  "proc-macro2",
  "prost-build",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3379,25 +3390,6 @@ dependencies = [
  "tracing",
 ]
 
-[[package]]
-name = "tower-http"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f873044bf02dd1e8239e9c1293ea39dad76dc594ec16185d0a1bf31d8dc8d858"
-dependencies = [
- "bitflags",
- "bytes",
- "futures-core",
- "futures-util",
- "http",
- "http-body",
- "http-range-header",
- "pin-project-lite",
- "tower",
- "tower-layer",
- "tower-service",
-]
-
 [[package]]
 name = "tower-layer"
 version = "0.3.2"
@@ -3425,9 +3417,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.7.2"
+version = "0.7.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4082e4d81173e0b7ad3cfb71e9eaef0dd0cbb7b139fdb56394f488a3b0760b23"
+checksum = "a230d51c76e70c5ff8edae9085d7d7161803a871880406a6772639def50d059c"
 dependencies = [
  "actix-web",
  "pin-project",
@@ -3443,7 +3435,7 @@ checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
 ]
 
 [[package]]
@@ -3563,15 +3555,15 @@ dependencies = [
 
 [[package]]
 name = "unicode-bidi"
-version = "0.3.10"
+version = "0.3.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d54675592c1dbefd78cbd98db9bacd89886e1ca50692a0692baefffdeb92dd58"
+checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.6"
+version = "1.0.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "84a22b9f218b40614adcb3f4ff08b703773ad44fa9423e4e0d346d5db86e4ebc"
+checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
 
 [[package]]
 name = "unicode-normalization"
@@ -3671,7 +3663,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "wasm-bindgen-shared",
 ]
 
@@ -3705,7 +3697,7 @@ checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn",
+ "syn 1.0.109",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
@@ -3826,9 +3818,9 @@ dependencies = [
 
 [[package]]
 name = "windows-targets"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e2522491fbfcd58cc84d47aeb2958948c4b8982e9a2d8a2a35bbaed431390e7"
+checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
 dependencies = [
  "windows_aarch64_gnullvm",
  "windows_aarch64_msvc",
@@ -3841,51 +3833,51 @@ dependencies = [
 
 [[package]]
 name = "windows_aarch64_gnullvm"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c9864e83243fdec7fc9c5444389dcbbfd258f745e7853198f365e3c4968a608"
+checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
 
 [[package]]
 name = "windows_aarch64_msvc"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c8b1b673ffc16c47a9ff48570a9d85e25d265735c503681332589af6253c6c7"
+checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
 
 [[package]]
 name = "windows_i686_gnu"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "de3887528ad530ba7bdbb1faa8275ec7a1155a45ffa57c37993960277145d640"
+checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
 
 [[package]]
 name = "windows_i686_msvc"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf4d1122317eddd6ff351aa852118a2418ad4214e6613a50e0191f7004372605"
+checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
 
 [[package]]
 name = "windows_x86_64_gnu"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1040f221285e17ebccbc2591ffdc2d44ee1f9186324dd3e84e99ac68d699c45"
+checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
 
 [[package]]
 name = "windows_x86_64_gnullvm"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "628bfdf232daa22b0d64fdb62b09fcc36bb01f05a3939e20ab73aaf9470d0463"
+checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
 
 [[package]]
 name = "windows_x86_64_msvc"
-version = "0.42.1"
+version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "447660ad36a13288b1db4d4248e857b510e8c3a225c822ba4fb748c0aafecffd"
+checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
 
 [[package]]
 name = "winnow"
-version = "0.3.3"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "faf09497b8f8b5ac5d3bb4d05c0a99be20f26fd3d5f2db7b0716e946d5103658"
+checksum = "deac0939bd6e4f24ab5919fbf751c97a8cfc8543bb083a305ed5c0c10bb241d1"
 dependencies = [
  "memchr",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 79dcc41..a06043d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -41,7 +41,7 @@ console-subscriber = { version = "0.1", optional = true }
 dashmap = "5.1.0"
 dotenv = "0.15.0"
 futures-util = "0.3.17"
-lru = "0.9.0"
+lru = "0.10.0"
 metrics = "0.20.1"
 metrics-exporter-prometheus = { version = "0.11.0", default-features = false, features = [
   "http-listener",
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..55f41fb
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,43 @@
+{
+  "nodes": {
+    "flake-utils": {
+      "locked": {
+        "lastModified": 1678901627,
+        "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
+        "type": "github"
+      },
+      "original": {
+        "owner": "numtide",
+        "repo": "flake-utils",
+        "type": "github"
+      }
+    },
+    "nixpkgs": {
+      "locked": {
+        "lastModified": 1679437018,
+        "narHash": "sha256-vOuiDPLHSEo/7NkiWtxpHpHgoXoNmrm+wkXZ6a072Fc=",
+        "owner": "NixOS",
+        "repo": "nixpkgs",
+        "rev": "19cf008bb18e47b6e3b4e16e32a9a4bdd4b45f7e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "NixOS",
+        "ref": "nixos-unstable",
+        "repo": "nixpkgs",
+        "type": "github"
+      }
+    },
+    "root": {
+      "inputs": {
+        "flake-utils": "flake-utils",
+        "nixpkgs": "nixpkgs"
+      }
+    }
+  },
+  "root": "root",
+  "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..70d1fe7
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,34 @@
+{
+  description = "relay";
+
+  inputs = {
+    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+    flake-utils.url = "github:numtide/flake-utils";
+  };
+
+  outputs = { self, nixpkgs, flake-utils }:
+    flake-utils.lib.eachDefaultSystem (system:
+      let
+        pkgs = import nixpkgs {
+          inherit system;
+        };
+      in
+      {
+        packages = rec {
+          relay = pkgs.callPackage ./relay.nix { };
+
+          default = relay;
+        };
+
+        apps = rec {
+          dev = flake-utils.lib.mkApp { drv = self.packages.${system}.pict-rs-proxy; };
+          default = dev;
+        };
+
+        devShell = with pkgs; mkShell {
+          nativeBuildInputs = [ cargo cargo-outdated cargo-zigbuild clippy gcc protobuf rust-analyzer rustc rustfmt ];
+
+          RUST_SRC_PATH = "${pkgs.rust.packages.stable.rustPlatform.rustLibSrc}";
+        };
+      });
+}
diff --git a/relay.nix b/relay.nix
new file mode 100644
index 0000000..6362fbe
--- /dev/null
+++ b/relay.nix
@@ -0,0 +1,27 @@
+{ lib
+, makeWrapper
+, nixosTests
+, protobuf
+, rustPlatform
+, stdenv
+}:
+
+rustPlatform.buildRustPackage {
+  pname = "relay";
+  version = "0.4.0-beta.1";
+  src = ./.;
+  cargoSha256 = "Kbicf3alz/QZJppBH4+dRhIf4extIONwBYnGF3TtqJ4=";
+
+  PROTOC = "${protobuf}/bin/protoc";
+  PROTOC_INCLUDE = "${protobuf}/include";
+
+  nativeBuildInputs = [ ];
+
+  passthru.tests = { inherit (nixosTests) relay; };
+
+  meta = with lib; {
+    description = "A simple image hosting service";
+    homepage = "https://git.asonix.dog/asonix/relay";
+    license = with licenses; [ agpl3Plus ];
+  };
+}

From 2cb5ad99178c2a7aef37f19896682bed2f72c657 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 23 Mar 2023 13:51:32 -0500
Subject: [PATCH 72/87] Replace Double with Fanout

---
 src/collector.rs        | 417 +++++++++++++++++++++++++++++++++++++++-
 src/collector/double.rs | 133 -------------
 src/collector/stats.rs  | 414 ---------------------------------------
 src/main.rs             |   9 +-
 4 files changed, 420 insertions(+), 553 deletions(-)
 delete mode 100644 src/collector/double.rs
 delete mode 100644 src/collector/stats.rs

diff --git a/src/collector.rs b/src/collector.rs
index b2758b0..91f235f 100644
--- a/src/collector.rs
+++ b/src/collector.rs
@@ -1,5 +1,414 @@
-mod double;
-mod stats;
+use metrics::{Key, Recorder, SetRecorderError};
+use metrics_util::{
+    registry::{AtomicStorage, GenerationalStorage, Recency, Registry},
+    MetricKindMask, Summary,
+};
+use quanta::Clock;
+use std::{
+    collections::{BTreeMap, HashMap},
+    sync::{atomic::Ordering, Arc, RwLock},
+    time::Duration,
+};
 
-pub(crate) use double::DoubleRecorder;
-pub(crate) use stats::{MemoryCollector, Snapshot};
+const SECONDS: u64 = 1;
+const MINUTES: u64 = 60 * SECONDS;
+const HOURS: u64 = 60 * MINUTES;
+const DAYS: u64 = 24 * HOURS;
+
+type DistributionMap = BTreeMap<Vec<(String, String)>, Summary>;
+
+#[derive(Clone)]
+pub struct MemoryCollector {
+    inner: Arc<Inner>,
+}
+
+struct Inner {
+    descriptions: RwLock<HashMap<String, metrics::SharedString>>,
+    distributions: RwLock<HashMap<String, DistributionMap>>,
+    recency: Recency<Key>,
+    registry: Registry<Key, GenerationalStorage<AtomicStorage>>,
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+struct Counter {
+    labels: BTreeMap<String, String>,
+    value: u64,
+}
+
+impl std::fmt::Display for Counter {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let labels = self
+            .labels
+            .iter()
+            .map(|(k, v)| format!("{k}: {v}"))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        write!(f, "{labels} - {}", self.value)
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+struct Gauge {
+    labels: BTreeMap<String, String>,
+    value: f64,
+}
+
+impl std::fmt::Display for Gauge {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let labels = self
+            .labels
+            .iter()
+            .map(|(k, v)| format!("{k}: {v}"))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        write!(f, "{labels} - {}", self.value)
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+struct Histogram {
+    labels: BTreeMap<String, String>,
+    value: Vec<(f64, Option<f64>)>,
+}
+
+impl std::fmt::Display for Histogram {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        let labels = self
+            .labels
+            .iter()
+            .map(|(k, v)| format!("{k}: {v}"))
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        let value = self
+            .value
+            .iter()
+            .map(|(k, v)| {
+                if let Some(v) = v {
+                    format!("{k}: {v:.6}")
+                } else {
+                    format!("{k}: None,")
+                }
+            })
+            .collect::<Vec<_>>()
+            .join(", ");
+
+        write!(f, "{labels} - {value}")
+    }
+}
+
+#[derive(Debug, serde::Deserialize, serde::Serialize)]
+pub(crate) struct Snapshot {
+    counters: HashMap<String, Vec<Counter>>,
+    gauges: HashMap<String, Vec<Gauge>>,
+    histograms: HashMap<String, Vec<Histogram>>,
+}
+
+const PAIRS: [((&str, &str), &str); 2] = [
+    (
+        (
+            "background-jobs.worker.started",
+            "background-jobs.worker.finished",
+        ),
+        "background-jobs.worker.running",
+    ),
+    (
+        (
+            "background-jobs.job.started",
+            "background-jobs.job.finished",
+        ),
+        "background-jobs.job.running",
+    ),
+];
+
+#[derive(Default)]
+struct MergeCounter {
+    start: Option<Counter>,
+    finish: Option<Counter>,
+}
+
+impl MergeCounter {
+    fn merge(self) -> Option<Counter> {
+        match (self.start, self.finish) {
+            (Some(start), Some(end)) => Some(Counter {
+                labels: start.labels,
+                value: start.value.saturating_sub(end.value),
+            }),
+            (Some(only), None) => Some(only),
+            (None, Some(only)) => Some(Counter {
+                labels: only.labels,
+                value: 0,
+            }),
+            (None, None) => None,
+        }
+    }
+}
+
+impl Snapshot {
+    pub(crate) fn present(self) {
+        if !self.counters.is_empty() {
+            println!("Counters");
+            let mut merging = HashMap::new();
+            for (key, counters) in self.counters {
+                if let Some(((start, _), name)) = PAIRS
+                    .iter()
+                    .find(|((start, finish), _)| *start == key || *finish == key)
+                {
+                    let entry = merging.entry(name).or_insert_with(HashMap::new);
+
+                    for counter in counters {
+                        let mut merge_counter = entry
+                            .entry(counter.labels.clone())
+                            .or_insert_with(MergeCounter::default);
+                        if key == *start {
+                            merge_counter.start = Some(counter);
+                        } else {
+                            merge_counter.finish = Some(counter);
+                        }
+                    }
+
+                    continue;
+                }
+
+                println!("\t{key}");
+                for counter in counters {
+                    println!("\t\t{counter}");
+                }
+            }
+
+            for (key, counters) in merging {
+                println!("\t{key}");
+
+                for (_, counter) in counters {
+                    if let Some(counter) = counter.merge() {
+                        println!("\t\t{counter}");
+                    }
+                }
+            }
+        }
+
+        if !self.gauges.is_empty() {
+            println!("Gauges");
+            for (key, gauges) in self.gauges {
+                println!("\t{key}");
+
+                for gauge in gauges {
+                    println!("\t\t{gauge}");
+                }
+            }
+        }
+
+        if !self.histograms.is_empty() {
+            println!("Histograms");
+            for (key, histograms) in self.histograms {
+                println!("\t{key}");
+
+                for histogram in histograms {
+                    println!("\t\t{histogram}");
+                }
+            }
+        }
+    }
+}
+
+fn key_to_parts(key: &Key) -> (String, Vec<(String, String)>) {
+    let labels = key
+        .labels()
+        .into_iter()
+        .map(|label| (label.key().to_string(), label.value().to_string()))
+        .collect();
+    let name = key.name().to_string();
+    (name, labels)
+}
+
+impl Inner {
+    fn snapshot_counters(&self) -> HashMap<String, Vec<Counter>> {
+        let mut counters = HashMap::new();
+
+        for (key, counter) in self.registry.get_counter_handles() {
+            let gen = counter.get_generation();
+            if !self.recency.should_store_counter(&key, gen, &self.registry) {
+                continue;
+            }
+
+            let (name, labels) = key_to_parts(&key);
+            let value = counter.get_inner().load(Ordering::Acquire);
+            counters.entry(name).or_insert_with(Vec::new).push(Counter {
+                labels: labels.into_iter().collect(),
+                value,
+            });
+        }
+
+        counters
+    }
+
+    fn snapshot_gauges(&self) -> HashMap<String, Vec<Gauge>> {
+        let mut gauges = HashMap::new();
+
+        for (key, gauge) in self.registry.get_gauge_handles() {
+            let gen = gauge.get_generation();
+            if !self.recency.should_store_gauge(&key, gen, &self.registry) {
+                continue;
+            }
+
+            let (name, labels) = key_to_parts(&key);
+            let value = f64::from_bits(gauge.get_inner().load(Ordering::Acquire));
+            gauges.entry(name).or_insert_with(Vec::new).push(Gauge {
+                labels: labels.into_iter().collect(),
+                value,
+            })
+        }
+
+        gauges
+    }
+
+    fn snapshot_histograms(&self) -> HashMap<String, Vec<Histogram>> {
+        for (key, histogram) in self.registry.get_histogram_handles() {
+            let gen = histogram.get_generation();
+            let (name, labels) = key_to_parts(&key);
+
+            if !self
+                .recency
+                .should_store_histogram(&key, gen, &self.registry)
+            {
+                let mut d = self.distributions.write().unwrap();
+                let delete_by_name = if let Some(by_name) = d.get_mut(&name) {
+                    by_name.remove(&labels);
+                    by_name.is_empty()
+                } else {
+                    false
+                };
+                drop(d);
+
+                if delete_by_name {
+                    self.descriptions.write().unwrap().remove(&name);
+                }
+
+                continue;
+            }
+
+            let mut d = self.distributions.write().unwrap();
+            let outer_entry = d.entry(name.clone()).or_insert_with(BTreeMap::new);
+
+            let entry = outer_entry
+                .entry(labels)
+                .or_insert_with(Summary::with_defaults);
+
+            histogram.get_inner().clear_with(|samples| {
+                for sample in samples {
+                    entry.add(*sample);
+                }
+            })
+        }
+
+        let d = self.distributions.read().unwrap().clone();
+        d.into_iter()
+            .map(|(key, value)| {
+                (
+                    key,
+                    value
+                        .into_iter()
+                        .map(|(labels, summary)| Histogram {
+                            labels: labels.into_iter().collect(),
+                            value: [0.001, 0.01, 0.05, 0.1, 0.5, 0.9, 0.99, 1.0]
+                                .into_iter()
+                                .map(|q| (q, summary.quantile(q)))
+                                .collect(),
+                        })
+                        .collect(),
+                )
+            })
+            .collect()
+    }
+
+    fn snapshot(&self) -> Snapshot {
+        Snapshot {
+            counters: self.snapshot_counters(),
+            gauges: self.snapshot_gauges(),
+            histograms: self.snapshot_histograms(),
+        }
+    }
+}
+
+impl MemoryCollector {
+    pub(crate) fn new() -> Self {
+        MemoryCollector {
+            inner: Arc::new(Inner {
+                descriptions: Default::default(),
+                distributions: Default::default(),
+                recency: Recency::new(
+                    Clock::new(),
+                    MetricKindMask::ALL,
+                    Some(Duration::from_secs(5 * DAYS)),
+                ),
+                registry: Registry::new(GenerationalStorage::atomic()),
+            }),
+        }
+    }
+
+    pub(crate) fn snapshot(&self) -> Snapshot {
+        self.inner.snapshot()
+    }
+
+    fn add_description_if_missing(
+        &self,
+        key: &metrics::KeyName,
+        description: metrics::SharedString,
+    ) {
+        let mut d = self.inner.descriptions.write().unwrap();
+        d.entry(key.as_str().to_owned()).or_insert(description);
+    }
+
+    pub(crate) fn install(&self) -> Result<(), SetRecorderError> {
+        metrics::set_boxed_recorder(Box::new(self.clone()))
+    }
+}
+
+impl Recorder for MemoryCollector {
+    fn describe_counter(
+        &self,
+        key: metrics::KeyName,
+        _: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.add_description_if_missing(&key, description)
+    }
+
+    fn describe_gauge(
+        &self,
+        key: metrics::KeyName,
+        _: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.add_description_if_missing(&key, description)
+    }
+
+    fn describe_histogram(
+        &self,
+        key: metrics::KeyName,
+        _: Option<metrics::Unit>,
+        description: metrics::SharedString,
+    ) {
+        self.add_description_if_missing(&key, description)
+    }
+
+    fn register_counter(&self, key: &Key) -> metrics::Counter {
+        self.inner
+            .registry
+            .get_or_create_counter(key, |c| c.clone().into())
+    }
+
+    fn register_gauge(&self, key: &Key) -> metrics::Gauge {
+        self.inner
+            .registry
+            .get_or_create_gauge(key, |c| c.clone().into())
+    }
+
+    fn register_histogram(&self, key: &Key) -> metrics::Histogram {
+        self.inner
+            .registry
+            .get_or_create_histogram(key, |c| c.clone().into())
+    }
+}
diff --git a/src/collector/double.rs b/src/collector/double.rs
deleted file mode 100644
index b78dbff..0000000
--- a/src/collector/double.rs
+++ /dev/null
@@ -1,133 +0,0 @@
-use metrics::{CounterFn, GaugeFn, HistogramFn, Key, Recorder, SetRecorderError};
-use std::sync::Arc;
-
-#[derive(Clone)]
-pub(crate) struct DoubleRecorder<R, S> {
-    first: R,
-    second: S,
-}
-
-struct DoubleCounter {
-    first: metrics::Counter,
-    second: metrics::Counter,
-}
-
-struct DoubleGauge {
-    first: metrics::Gauge,
-    second: metrics::Gauge,
-}
-
-struct DoubleHistogram {
-    first: metrics::Histogram,
-    second: metrics::Histogram,
-}
-
-impl<R, S> DoubleRecorder<R, S> {
-    pub(crate) fn new(first: R, second: S) -> Self {
-        DoubleRecorder { first, second }
-    }
-
-    pub(crate) fn install(self) -> Result<(), SetRecorderError>
-    where
-        R: Recorder + 'static,
-        S: Recorder + 'static,
-    {
-        metrics::set_boxed_recorder(Box::new(self))
-    }
-}
-
-impl<R, S> Recorder for DoubleRecorder<R, S>
-where
-    R: Recorder,
-    S: Recorder,
-{
-    fn describe_counter(
-        &self,
-        key: metrics::KeyName,
-        unit: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.first
-            .describe_counter(key.clone(), unit, description.clone());
-        self.second.describe_counter(key, unit, description);
-    }
-
-    fn describe_gauge(
-        &self,
-        key: metrics::KeyName,
-        unit: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.first
-            .describe_gauge(key.clone(), unit, description.clone());
-        self.second.describe_gauge(key, unit, description);
-    }
-
-    fn describe_histogram(
-        &self,
-        key: metrics::KeyName,
-        unit: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.first
-            .describe_histogram(key.clone(), unit, description.clone());
-        self.second.describe_histogram(key, unit, description);
-    }
-
-    fn register_counter(&self, key: &Key) -> metrics::Counter {
-        let first = self.first.register_counter(key);
-        let second = self.second.register_counter(key);
-
-        metrics::Counter::from_arc(Arc::new(DoubleCounter { first, second }))
-    }
-
-    fn register_gauge(&self, key: &Key) -> metrics::Gauge {
-        let first = self.first.register_gauge(key);
-        let second = self.second.register_gauge(key);
-
-        metrics::Gauge::from_arc(Arc::new(DoubleGauge { first, second }))
-    }
-
-    fn register_histogram(&self, key: &Key) -> metrics::Histogram {
-        let first = self.first.register_histogram(key);
-        let second = self.second.register_histogram(key);
-
-        metrics::Histogram::from_arc(Arc::new(DoubleHistogram { first, second }))
-    }
-}
-
-impl CounterFn for DoubleCounter {
-    fn increment(&self, value: u64) {
-        self.first.increment(value);
-        self.second.increment(value);
-    }
-
-    fn absolute(&self, value: u64) {
-        self.first.absolute(value);
-        self.second.absolute(value);
-    }
-}
-
-impl GaugeFn for DoubleGauge {
-    fn increment(&self, value: f64) {
-        self.first.increment(value);
-        self.second.increment(value);
-    }
-
-    fn decrement(&self, value: f64) {
-        self.first.decrement(value);
-        self.second.decrement(value);
-    }
-
-    fn set(&self, value: f64) {
-        self.first.set(value);
-        self.second.set(value);
-    }
-}
-
-impl HistogramFn for DoubleHistogram {
-    fn record(&self, value: f64) {
-        self.first.record(value);
-        self.second.record(value);
-    }
-}
diff --git a/src/collector/stats.rs b/src/collector/stats.rs
deleted file mode 100644
index 91f235f..0000000
--- a/src/collector/stats.rs
+++ /dev/null
@@ -1,414 +0,0 @@
-use metrics::{Key, Recorder, SetRecorderError};
-use metrics_util::{
-    registry::{AtomicStorage, GenerationalStorage, Recency, Registry},
-    MetricKindMask, Summary,
-};
-use quanta::Clock;
-use std::{
-    collections::{BTreeMap, HashMap},
-    sync::{atomic::Ordering, Arc, RwLock},
-    time::Duration,
-};
-
-const SECONDS: u64 = 1;
-const MINUTES: u64 = 60 * SECONDS;
-const HOURS: u64 = 60 * MINUTES;
-const DAYS: u64 = 24 * HOURS;
-
-type DistributionMap = BTreeMap<Vec<(String, String)>, Summary>;
-
-#[derive(Clone)]
-pub struct MemoryCollector {
-    inner: Arc<Inner>,
-}
-
-struct Inner {
-    descriptions: RwLock<HashMap<String, metrics::SharedString>>,
-    distributions: RwLock<HashMap<String, DistributionMap>>,
-    recency: Recency<Key>,
-    registry: Registry<Key, GenerationalStorage<AtomicStorage>>,
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-struct Counter {
-    labels: BTreeMap<String, String>,
-    value: u64,
-}
-
-impl std::fmt::Display for Counter {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let labels = self
-            .labels
-            .iter()
-            .map(|(k, v)| format!("{k}: {v}"))
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        write!(f, "{labels} - {}", self.value)
-    }
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-struct Gauge {
-    labels: BTreeMap<String, String>,
-    value: f64,
-}
-
-impl std::fmt::Display for Gauge {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let labels = self
-            .labels
-            .iter()
-            .map(|(k, v)| format!("{k}: {v}"))
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        write!(f, "{labels} - {}", self.value)
-    }
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-struct Histogram {
-    labels: BTreeMap<String, String>,
-    value: Vec<(f64, Option<f64>)>,
-}
-
-impl std::fmt::Display for Histogram {
-    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        let labels = self
-            .labels
-            .iter()
-            .map(|(k, v)| format!("{k}: {v}"))
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        let value = self
-            .value
-            .iter()
-            .map(|(k, v)| {
-                if let Some(v) = v {
-                    format!("{k}: {v:.6}")
-                } else {
-                    format!("{k}: None,")
-                }
-            })
-            .collect::<Vec<_>>()
-            .join(", ");
-
-        write!(f, "{labels} - {value}")
-    }
-}
-
-#[derive(Debug, serde::Deserialize, serde::Serialize)]
-pub(crate) struct Snapshot {
-    counters: HashMap<String, Vec<Counter>>,
-    gauges: HashMap<String, Vec<Gauge>>,
-    histograms: HashMap<String, Vec<Histogram>>,
-}
-
-const PAIRS: [((&str, &str), &str); 2] = [
-    (
-        (
-            "background-jobs.worker.started",
-            "background-jobs.worker.finished",
-        ),
-        "background-jobs.worker.running",
-    ),
-    (
-        (
-            "background-jobs.job.started",
-            "background-jobs.job.finished",
-        ),
-        "background-jobs.job.running",
-    ),
-];
-
-#[derive(Default)]
-struct MergeCounter {
-    start: Option<Counter>,
-    finish: Option<Counter>,
-}
-
-impl MergeCounter {
-    fn merge(self) -> Option<Counter> {
-        match (self.start, self.finish) {
-            (Some(start), Some(end)) => Some(Counter {
-                labels: start.labels,
-                value: start.value.saturating_sub(end.value),
-            }),
-            (Some(only), None) => Some(only),
-            (None, Some(only)) => Some(Counter {
-                labels: only.labels,
-                value: 0,
-            }),
-            (None, None) => None,
-        }
-    }
-}
-
-impl Snapshot {
-    pub(crate) fn present(self) {
-        if !self.counters.is_empty() {
-            println!("Counters");
-            let mut merging = HashMap::new();
-            for (key, counters) in self.counters {
-                if let Some(((start, _), name)) = PAIRS
-                    .iter()
-                    .find(|((start, finish), _)| *start == key || *finish == key)
-                {
-                    let entry = merging.entry(name).or_insert_with(HashMap::new);
-
-                    for counter in counters {
-                        let mut merge_counter = entry
-                            .entry(counter.labels.clone())
-                            .or_insert_with(MergeCounter::default);
-                        if key == *start {
-                            merge_counter.start = Some(counter);
-                        } else {
-                            merge_counter.finish = Some(counter);
-                        }
-                    }
-
-                    continue;
-                }
-
-                println!("\t{key}");
-                for counter in counters {
-                    println!("\t\t{counter}");
-                }
-            }
-
-            for (key, counters) in merging {
-                println!("\t{key}");
-
-                for (_, counter) in counters {
-                    if let Some(counter) = counter.merge() {
-                        println!("\t\t{counter}");
-                    }
-                }
-            }
-        }
-
-        if !self.gauges.is_empty() {
-            println!("Gauges");
-            for (key, gauges) in self.gauges {
-                println!("\t{key}");
-
-                for gauge in gauges {
-                    println!("\t\t{gauge}");
-                }
-            }
-        }
-
-        if !self.histograms.is_empty() {
-            println!("Histograms");
-            for (key, histograms) in self.histograms {
-                println!("\t{key}");
-
-                for histogram in histograms {
-                    println!("\t\t{histogram}");
-                }
-            }
-        }
-    }
-}
-
-fn key_to_parts(key: &Key) -> (String, Vec<(String, String)>) {
-    let labels = key
-        .labels()
-        .into_iter()
-        .map(|label| (label.key().to_string(), label.value().to_string()))
-        .collect();
-    let name = key.name().to_string();
-    (name, labels)
-}
-
-impl Inner {
-    fn snapshot_counters(&self) -> HashMap<String, Vec<Counter>> {
-        let mut counters = HashMap::new();
-
-        for (key, counter) in self.registry.get_counter_handles() {
-            let gen = counter.get_generation();
-            if !self.recency.should_store_counter(&key, gen, &self.registry) {
-                continue;
-            }
-
-            let (name, labels) = key_to_parts(&key);
-            let value = counter.get_inner().load(Ordering::Acquire);
-            counters.entry(name).or_insert_with(Vec::new).push(Counter {
-                labels: labels.into_iter().collect(),
-                value,
-            });
-        }
-
-        counters
-    }
-
-    fn snapshot_gauges(&self) -> HashMap<String, Vec<Gauge>> {
-        let mut gauges = HashMap::new();
-
-        for (key, gauge) in self.registry.get_gauge_handles() {
-            let gen = gauge.get_generation();
-            if !self.recency.should_store_gauge(&key, gen, &self.registry) {
-                continue;
-            }
-
-            let (name, labels) = key_to_parts(&key);
-            let value = f64::from_bits(gauge.get_inner().load(Ordering::Acquire));
-            gauges.entry(name).or_insert_with(Vec::new).push(Gauge {
-                labels: labels.into_iter().collect(),
-                value,
-            })
-        }
-
-        gauges
-    }
-
-    fn snapshot_histograms(&self) -> HashMap<String, Vec<Histogram>> {
-        for (key, histogram) in self.registry.get_histogram_handles() {
-            let gen = histogram.get_generation();
-            let (name, labels) = key_to_parts(&key);
-
-            if !self
-                .recency
-                .should_store_histogram(&key, gen, &self.registry)
-            {
-                let mut d = self.distributions.write().unwrap();
-                let delete_by_name = if let Some(by_name) = d.get_mut(&name) {
-                    by_name.remove(&labels);
-                    by_name.is_empty()
-                } else {
-                    false
-                };
-                drop(d);
-
-                if delete_by_name {
-                    self.descriptions.write().unwrap().remove(&name);
-                }
-
-                continue;
-            }
-
-            let mut d = self.distributions.write().unwrap();
-            let outer_entry = d.entry(name.clone()).or_insert_with(BTreeMap::new);
-
-            let entry = outer_entry
-                .entry(labels)
-                .or_insert_with(Summary::with_defaults);
-
-            histogram.get_inner().clear_with(|samples| {
-                for sample in samples {
-                    entry.add(*sample);
-                }
-            })
-        }
-
-        let d = self.distributions.read().unwrap().clone();
-        d.into_iter()
-            .map(|(key, value)| {
-                (
-                    key,
-                    value
-                        .into_iter()
-                        .map(|(labels, summary)| Histogram {
-                            labels: labels.into_iter().collect(),
-                            value: [0.001, 0.01, 0.05, 0.1, 0.5, 0.9, 0.99, 1.0]
-                                .into_iter()
-                                .map(|q| (q, summary.quantile(q)))
-                                .collect(),
-                        })
-                        .collect(),
-                )
-            })
-            .collect()
-    }
-
-    fn snapshot(&self) -> Snapshot {
-        Snapshot {
-            counters: self.snapshot_counters(),
-            gauges: self.snapshot_gauges(),
-            histograms: self.snapshot_histograms(),
-        }
-    }
-}
-
-impl MemoryCollector {
-    pub(crate) fn new() -> Self {
-        MemoryCollector {
-            inner: Arc::new(Inner {
-                descriptions: Default::default(),
-                distributions: Default::default(),
-                recency: Recency::new(
-                    Clock::new(),
-                    MetricKindMask::ALL,
-                    Some(Duration::from_secs(5 * DAYS)),
-                ),
-                registry: Registry::new(GenerationalStorage::atomic()),
-            }),
-        }
-    }
-
-    pub(crate) fn snapshot(&self) -> Snapshot {
-        self.inner.snapshot()
-    }
-
-    fn add_description_if_missing(
-        &self,
-        key: &metrics::KeyName,
-        description: metrics::SharedString,
-    ) {
-        let mut d = self.inner.descriptions.write().unwrap();
-        d.entry(key.as_str().to_owned()).or_insert(description);
-    }
-
-    pub(crate) fn install(&self) -> Result<(), SetRecorderError> {
-        metrics::set_boxed_recorder(Box::new(self.clone()))
-    }
-}
-
-impl Recorder for MemoryCollector {
-    fn describe_counter(
-        &self,
-        key: metrics::KeyName,
-        _: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.add_description_if_missing(&key, description)
-    }
-
-    fn describe_gauge(
-        &self,
-        key: metrics::KeyName,
-        _: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.add_description_if_missing(&key, description)
-    }
-
-    fn describe_histogram(
-        &self,
-        key: metrics::KeyName,
-        _: Option<metrics::Unit>,
-        description: metrics::SharedString,
-    ) {
-        self.add_description_if_missing(&key, description)
-    }
-
-    fn register_counter(&self, key: &Key) -> metrics::Counter {
-        self.inner
-            .registry
-            .get_or_create_counter(key, |c| c.clone().into())
-    }
-
-    fn register_gauge(&self, key: &Key) -> metrics::Gauge {
-        self.inner
-            .registry
-            .get_or_create_gauge(key, |c| c.clone().into())
-    }
-
-    fn register_histogram(&self, key: &Key) -> metrics::Histogram {
-        self.inner
-            .registry
-            .get_or_create_histogram(key, |c| c.clone().into())
-    }
-}
diff --git a/src/main.rs b/src/main.rs
index 22764a2..5f733d7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -4,11 +4,12 @@
 use activitystreams::iri_string::types::IriString;
 use actix_rt::task::JoinHandle;
 use actix_web::{middleware::Compress, web, App, HttpServer};
-use collector::{DoubleRecorder, MemoryCollector};
+use collector::MemoryCollector;
 #[cfg(feature = "console")]
 use console_subscriber::ConsoleLayer;
 use http_signature_normalization_actix::middleware::VerifySignature;
 use metrics_exporter_prometheus::PrometheusBuilder;
+use metrics_util::layers::FanoutBuilder;
 use opentelemetry::{sdk::Resource, KeyValue};
 use opentelemetry_otlp::WithExportConfig;
 use rustls::ServerConfig;
@@ -119,7 +120,11 @@ async fn main() -> Result<(), anyhow::Error> {
             .build()?;
 
         actix_rt::spawn(exporter);
-        DoubleRecorder::new(recorder, collector.clone()).install()?;
+        let recorder = FanoutBuilder::default()
+            .add_recorder(recorder)
+            .add_recorder(collector.clone())
+            .build();
+        metrics::set_boxed_recorder(Box::new(recorder))?;
     } else {
         collector.install()?;
     }

From 73bf4d1597230c3c6aa9d08525156642f17bd941 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 23 Mar 2023 14:37:33 -0500
Subject: [PATCH 73/87] Remove unneeded .into_iter()

---
 src/collector.rs | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/collector.rs b/src/collector.rs
index 91f235f..56a533d 100644
--- a/src/collector.rs
+++ b/src/collector.rs
@@ -216,7 +216,6 @@ impl Snapshot {
 fn key_to_parts(key: &Key) -> (String, Vec<(String, String)>) {
     let labels = key
         .labels()
-        .into_iter()
         .map(|label| (label.key().to_string(), label.value().to_string()))
         .collect();
     let name = key.name().to_string();

From ab2dbfb439b0ea86d00d495d53ee1c5744020a01 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 27 Apr 2023 19:34:23 -0500
Subject: [PATCH 74/87] Update metrics, rsa

---
 Cargo.lock                 | 648 +++++++++++++++++++++----------------
 Cargo.toml                 |  14 +-
 src/middleware/verifier.rs |   2 +-
 src/requests.rs            |   6 +-
 4 files changed, 385 insertions(+), 285 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 795a5f7..f094062 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -43,7 +43,7 @@ version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
  "bytes",
  "futures-core",
  "futures-sink",
@@ -67,7 +67,7 @@ dependencies = [
  "actix-utils",
  "ahash 0.8.3",
  "base64 0.21.0",
- "bitflags 1.3.2",
+ "bitflags",
  "brotli",
  "bytes",
  "bytestring",
@@ -276,6 +276,15 @@ dependencies = [
  "memchr",
 ]
 
+[[package]]
+name = "aho-corasick"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+dependencies = [
+ "memchr",
+]
+
 [[package]]
 name = "alloc-no-stdlib"
 version = "2.0.4"
@@ -304,6 +313,55 @@ dependencies = [
  "url",
 ]
 
+[[package]]
+name = "anstream"
+version = "0.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is-terminal",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
+dependencies = [
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.48.0",
+]
+
 [[package]]
 name = "anyhow"
 version = "1.0.70"
@@ -388,9 +446,9 @@ checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
 
 [[package]]
 name = "async-stream"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e"
+checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51"
 dependencies = [
  "async-stream-impl",
  "futures-core",
@@ -399,24 +457,24 @@ dependencies = [
 
 [[package]]
 name = "async-stream-impl"
-version = "0.3.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965"
+checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "async-trait"
-version = "0.1.67"
+version = "0.1.68"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86ea188f25f0255d8f92797797c97ebf5631fa88178beb1a46fdf5622c9a00e4"
+checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -461,13 +519,13 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.6.12"
+version = "0.6.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "349f8ccfd9221ee7d1f3d4b33e1f8319b3a81ed8f61f2ea40b37b859794b4491"
+checksum = "b70caf9f1b0c045f7da350636435b775a9733adf2df56e8aa2a29210fbc335d4"
 dependencies = [
  "async-trait",
  "axum-core",
- "bitflags 1.3.2",
+ "bitflags",
  "bytes",
  "futures-util",
  "http",
@@ -489,9 +547,9 @@ dependencies = [
 
 [[package]]
 name = "axum-core"
-version = "0.3.3"
+version = "0.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e"
+checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
 dependencies = [
  "async-trait",
  "bytes",
@@ -506,9 +564,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs"
-version = "0.14.1"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7d6695c1cc80d11c6a48974c57289b020a24426cad4284c329374f114997a8a"
+checksum = "a0788884be043a6ea4812f533b53f47180f1fb68a45d6a1e7c9f55369f187bd9"
 dependencies = [
  "background-jobs-actix",
  "background-jobs-core",
@@ -516,9 +574,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-actix"
-version = "0.14.5"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6c7b21d56df90647f9bef717379663f8d92374f3707d95890a3e6da2f8a7359"
+checksum = "6918aac07d254c283e83e74d94d2a4137eb8eb2bb35749553b2aeedefc13243d"
 dependencies = [
  "actix-rt",
  "anyhow",
@@ -536,9 +594,9 @@ dependencies = [
 
 [[package]]
 name = "background-jobs-core"
-version = "0.14.4"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21825e3893be7b103cd52cf3ee65db388b35816b5ec1229032b342a334eef533"
+checksum = "19188ccc4964d2d7ac0349ec05290b079c49a6218dc9a70516c9084790efc039"
 dependencies = [
  "actix-rt",
  "anyhow",
@@ -591,12 +649,6 @@ version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
 
-[[package]]
-name = "bitflags"
-version = "2.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "487f1e0fcbe47deb8b0574e646def1c903389d95241dd1bbcc6ce4a715dfc0c1"
-
 [[package]]
 name = "block-buffer"
 version = "0.10.4"
@@ -639,9 +691,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.12.0"
+version = "3.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535"
+checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
 
 [[package]]
 name = "bytecount"
@@ -704,39 +756,51 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.1.12"
+version = "4.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76e21918af71fb4bcd813230cf549e33d14f73d0326b932b630ce2930332b131"
+checksum = "8a1f23fa97e1d1641371b51f35535cb26959b8e27ab50d167a8b996b5bada819"
 dependencies = [
- "bitflags 2.0.2",
+ "clap_builder",
  "clap_derive",
- "clap_lex",
- "is-terminal",
  "once_cell",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0fdc5d93c358224b4d6867ef1356d740de2303e9892edc06c5340daeccd96bab"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "bitflags",
+ "clap_lex",
  "strsim",
- "termcolor",
 ]
 
 [[package]]
 name = "clap_derive"
-version = "4.1.12"
+version = "4.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a932373bab67b984c790ddf2c9ca295d8e3af3b7ef92de5a5bacdccdee4b09b"
+checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
 dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "clap_lex"
-version = "0.3.3"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "033f6b7a4acb1f358c742aaca805c939ee73b4c6209ae4318ec7aca81c42e646"
-dependencies = [
- "os_str_bytes",
-]
+checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
 
 [[package]]
 name = "config"
@@ -807,9 +871,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.5"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320"
+checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
 dependencies = [
  "libc",
 ]
@@ -825,9 +889,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-channel"
-version = "0.5.7"
+version = "0.5.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf2b3e8478797446514c91ef04bafcb59faba183e621ad488df88983cc14128c"
+checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
 dependencies = [
  "cfg-if",
  "crossbeam-utils",
@@ -926,9 +990,9 @@ dependencies = [
 
 [[package]]
 name = "der"
-version = "0.6.1"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
+checksum = "05e58dffcdcc8ee7b22f0c1f71a69243d7c2d9ad87b5a14361f2424a1565c219"
 dependencies = [
  "const-oid",
  "pem-rfc7468",
@@ -1013,13 +1077,13 @@ dependencies = [
 
 [[package]]
 name = "errno"
-version = "0.2.8"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1"
+checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
 dependencies = [
  "errno-dragonfly",
  "libc",
- "winapi",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1100,9 +1164,9 @@ dependencies = [
 
 [[package]]
 name = "futures"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "531ac96c6ff5fd7c62263c5e3c67a603af4fcaee2e1a0ae5565ba3a11e69e549"
+checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1115,9 +1179,9 @@ dependencies = [
 
 [[package]]
 name = "futures-channel"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "164713a5a0dcc3e7b4b1ed7d3b433cabc18025386f9339346e8daf15963cf7ac"
+checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2"
 dependencies = [
  "futures-core",
  "futures-sink",
@@ -1125,15 +1189,15 @@ dependencies = [
 
 [[package]]
 name = "futures-core"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "86d7a0c1aa76363dac491de0ee99faf6941128376f1cf96f07db7603b7de69dd"
+checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c"
 
 [[package]]
 name = "futures-executor"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1997dd9df74cdac935c76252744c1ed5794fac083242ea4fe77ef3ed60ba0f83"
+checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0"
 dependencies = [
  "futures-core",
  "futures-task",
@@ -1142,38 +1206,38 @@ dependencies = [
 
 [[package]]
 name = "futures-io"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "89d422fa3cbe3b40dca574ab087abb5bc98258ea57eea3fd6f1fa7162c778b91"
+checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964"
 
 [[package]]
 name = "futures-macro"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3eb14ed937631bd8b8b8977f2c198443447a8355b6e3ca599f38c975e5a963b6"
+checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "futures-sink"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ec93083a4aecafb2a80a885c9de1f0ccae9dbd32c2bb54b0c3a65690e0b8d2f2"
+checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
 
 [[package]]
 name = "futures-task"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd65540d33b37b16542a0438c12e6aeead10d4ac5d05bd3f805b8f35ab592879"
+checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65"
 
 [[package]]
 name = "futures-util"
-version = "0.3.27"
+version = "0.3.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ef6b17e481503ec85211fed8f39d1970f128935ca1f814cd32ac4a6842e84ab"
+checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533"
 dependencies = [
  "futures-channel",
  "futures-core",
@@ -1198,9 +1262,9 @@ dependencies = [
 
 [[package]]
 name = "generic-array"
-version = "0.14.6"
+version = "0.14.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
+checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
 dependencies = [
  "typenum",
  "version_check",
@@ -1208,20 +1272,20 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31"
+checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
 dependencies = [
  "cfg-if",
  "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
 ]
 
 [[package]]
 name = "h2"
-version = "0.3.16"
+version = "0.3.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5be7b54589b581f624f566bf5d8eb2bab1db736c51528720b6bd36b96b55924d"
+checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
 dependencies = [
  "bytes",
  "fnv",
@@ -1374,9 +1438,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
 
 [[package]]
 name = "hyper"
-version = "0.14.25"
+version = "0.14.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc5e554ff619822309ffd57d8734d77cd5ce6238bc956f037ea06c58238c9899"
+checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -1439,9 +1503,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "1.9.2"
+version = "1.9.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885e79c1fc4b10f0e172c475f458b7f7b93061064d98c3293e98c5ba0c8b399"
+checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
 dependencies = [
  "autocfg",
  "hashbrown 0.12.3",
@@ -1467,20 +1531,20 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.9"
+version = "1.0.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb"
+checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
 dependencies = [
  "hermit-abi 0.3.1",
  "libc",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
 name = "ipnet"
-version = "2.7.1"
+version = "2.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30e22bd8629359895450b59ea7a776c850561b96a3b1d31321c1949d9e6c9146"
+checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f"
 
 [[package]]
 name = "iri-string"
@@ -1494,14 +1558,14 @@ dependencies = [
 
 [[package]]
 name = "is-terminal"
-version = "0.4.5"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8687c819457e979cc940d09cb16e42a1bf70aa6b60a549de6d3a62a0ee90c69e"
+checksum = "adcf93614601c8129ddf72e2d5633df827ba6551541c6d8c59520a371475be1f"
 dependencies = [
  "hermit-abi 0.3.1",
  "io-lifetimes",
  "rustix",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -1565,9 +1629,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.140"
+version = "0.2.142"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c"
+checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
 
 [[package]]
 name = "libm"
@@ -1583,9 +1647,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.1.4"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4"
+checksum = "2e8776872cdc2f073ccaab02e336fa321328c1e02646ebcb9d2108d0baab480d"
 
 [[package]]
 name = "local-channel"
@@ -1640,10 +1704,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
 
 [[package]]
-name = "mach"
-version = "0.3.2"
+name = "mach2"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b823e83b2affd8f40a9ee8c29dbc56404c1e34cd2710921f2801e2cf29527afa"
+checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
 dependencies = [
  "libc",
 ]
@@ -1706,28 +1770,26 @@ dependencies = [
 
 [[package]]
 name = "metrics"
-version = "0.20.1"
+version = "0.21.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849"
+checksum = "aa8ebbd1a9e57bbab77b9facae7f5136aea44c356943bf9a198f647da64285d6"
 dependencies = [
- "ahash 0.7.6",
+ "ahash 0.8.3",
  "metrics-macros",
  "portable-atomic",
 ]
 
 [[package]]
 name = "metrics-exporter-prometheus"
-version = "0.11.0"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8603921e1f54ef386189335f288441af761e0fc61bcb552168d9cedfe63ebc70"
+checksum = "5142a593c2be0cf5c2ac5b22ec7a4f74477b851efb6238236af26c6b5ca6e98e"
 dependencies = [
  "hyper",
  "indexmap",
  "ipnet",
  "metrics",
  "metrics-util",
- "parking_lot 0.12.1",
- "portable-atomic",
  "quanta",
  "thiserror",
  "tokio",
@@ -1735,31 +1797,29 @@ dependencies = [
 
 [[package]]
 name = "metrics-macros"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "731f8ecebd9f3a4aa847dfe75455e4757a45da40a7793d2f0b1f9b6ed18b23f3"
+checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "metrics-util"
-version = "0.14.0"
+version = "0.15.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7d24dc2dbae22bff6f1f9326ffce828c9f07ef9cc1e8002e5279f845432a30a"
+checksum = "111cb375987443c3de8d503580b536f77dc8416d32db62d9456db5d93bd7ac47"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 0.7.20",
  "crossbeam-epoch",
  "crossbeam-utils",
- "hashbrown 0.12.3",
+ "hashbrown 0.13.2",
  "indexmap",
  "metrics",
  "num_cpus",
  "ordered-float",
- "parking_lot 0.12.1",
- "portable-atomic",
  "quanta",
  "radix_trie",
  "sketches-ddsketch",
@@ -1787,7 +1847,7 @@ version = "0.10.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7754d4669873379ea6a8a5b56e406eb83de713af8a791517ef35a0c832b1e7d5"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 0.7.20",
  "css-minify",
  "lazy_static",
  "memchr",
@@ -1828,7 +1888,7 @@ checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
 dependencies = [
  "libc",
  "log",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
  "windows-sys 0.45.0",
 ]
 
@@ -2049,9 +2109,9 @@ dependencies = [
 
 [[package]]
 name = "ordered-float"
-version = "2.10.0"
+version = "3.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7940cf2ca942593318d07fcf2596cdca60a85c9e7fab408a5e21a4f9dcd40d87"
+checksum = "2fc2dbde8f8a79f2102cc474ceb0ad68e3b80b85289ea62389b60e66777e4213"
 dependencies = [
  "num-traits",
 ]
@@ -2066,12 +2126,6 @@ dependencies = [
  "hashbrown 0.12.3",
 ]
 
-[[package]]
-name = "os_str_bytes"
-version = "6.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267"
-
 [[package]]
 name = "overload"
 version = "0.1.1"
@@ -2108,7 +2162,7 @@ dependencies = [
  "cfg-if",
  "instant",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.2.16",
  "smallvec",
  "winapi",
 ]
@@ -2121,7 +2175,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.2.16",
  "smallvec",
  "windows-sys 0.45.0",
 ]
@@ -2132,7 +2186,7 @@ version = "0.10.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "30534759e6ad87aa144c396544747e1c25b1020bd133356fd758c8facec764e5"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 0.7.20",
  "lazy_static",
  "memchr",
 ]
@@ -2151,9 +2205,9 @@ checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd"
 
 [[package]]
 name = "pem-rfc7468"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d159833a9105500e0398934e205e0773f0b27529557134ecfc51c27646adac"
+checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
 dependencies = [
  "base64ct",
 ]
@@ -2166,9 +2220,9 @@ checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
 
 [[package]]
 name = "pest"
-version = "2.5.6"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cbd939b234e95d72bc393d51788aec68aeeb5d51e748ca08ff3aad58cb722f7"
+checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2176,9 +2230,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.5.6"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a81186863f3d0a27340815be8f2078dd8050b14cd71913db9fbda795e5f707d7"
+checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2186,22 +2240,22 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.5.6"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75a1ef20bf3193c15ac345acb32e26b3dc3223aff4d77ae4fc5359567683796b"
+checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e"
 dependencies = [
  "pest",
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "pest_meta"
-version = "2.5.6"
+version = "2.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5e3b284b1f13a20dc5ebc90aff59a51b8d7137c221131b52a7260c08cbc1cc80"
+checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
 dependencies = [
  "once_cell",
  "pest",
@@ -2290,21 +2344,20 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
 name = "pkcs1"
-version = "0.4.1"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719"
+checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
 dependencies = [
  "der",
  "pkcs8",
  "spki",
- "zeroize",
 ]
 
 [[package]]
 name = "pkcs8"
-version = "0.9.0"
+version = "0.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
 dependencies = [
  "der",
  "spki",
@@ -2312,9 +2365,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "0.3.19"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26f6a7b87c2e435a3241addceeeff740ff8b7e76b74c13bf9acb17fa454ea00b"
+checksum = "f602a0d1e09a48e4f8e8b4d4042e32807c3676da31f2ecabeac9f96226ec6c45"
 
 [[package]]
 name = "ppv-lite86"
@@ -2364,18 +2417,18 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.53"
+version = "1.0.56"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba466839c78239c09faf015484e5cc04860f88242cff4d03eb038f04b4699b73"
+checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "prost"
-version = "0.11.8"
+version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e48e50df39172a3e7eb17e14642445da64996989bc212b583015435d39a58537"
+checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
 dependencies = [
  "bytes",
  "prost-derive",
@@ -2383,9 +2436,9 @@ dependencies = [
 
 [[package]]
 name = "prost-build"
-version = "0.11.8"
+version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c828f93f5ca4826f97fedcbd3f9a536c16b12cff3dbbb4a007f932bbad95b12"
+checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
 dependencies = [
  "bytes",
  "heck",
@@ -2405,9 +2458,9 @@ dependencies = [
 
 [[package]]
 name = "prost-derive"
-version = "0.11.8"
+version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ea9b0f8cbe5e15a8a042d030bd96668db28ecb567ec37d691971ff5731d2b1b"
+checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
 dependencies = [
  "anyhow",
  "itertools 0.10.5",
@@ -2418,25 +2471,25 @@ dependencies = [
 
 [[package]]
 name = "prost-types"
-version = "0.11.8"
+version = "0.11.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "379119666929a1afd7a043aa6cf96fa67a6dce9af60c88095a4686dbce4c9c88"
+checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
 dependencies = [
  "prost",
 ]
 
 [[package]]
 name = "quanta"
-version = "0.10.1"
+version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e31331286705f455e56cca62e0e717158474ff02b7936c1fa596d983f4ae27"
+checksum = "8cc73c42f9314c4bdce450c77e6f09ecbddefbeddb1b5979ded332a3913ded33"
 dependencies = [
  "crossbeam-utils",
  "libc",
- "mach",
+ "mach2",
  "once_cell",
  "raw-cpuid",
- "wasi 0.10.2+wasi-snapshot-preview1",
+ "wasi",
  "web-sys",
  "winapi",
 ]
@@ -2496,7 +2549,7 @@ version = "10.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
 ]
 
 [[package]]
@@ -2514,18 +2567,27 @@ version = "0.2.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.3.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+dependencies = [
+ "bitflags",
 ]
 
 [[package]]
 name = "regex"
-version = "1.7.2"
+version = "1.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cce168fea28d3e05f158bda4576cf0c844d5045bc2cc3620fa0292ed5bb5814c"
+checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
 dependencies = [
- "aho-corasick",
+ "aho-corasick 1.0.1",
  "memchr",
- "regex-syntax",
+ "regex-syntax 0.7.1",
 ]
 
 [[package]]
@@ -2534,7 +2596,7 @@ version = "0.1.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
 dependencies = [
- "regex-syntax",
+ "regex-syntax 0.6.29",
 ]
 
 [[package]]
@@ -2544,10 +2606,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
-name = "reqwest"
-version = "0.11.15"
+name = "regex-syntax"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ba30cc2c0cd02af1222ed216ba659cdb2f879dfe3181852fe7c50b1d0005949"
+checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+
+[[package]]
+name = "reqwest"
+version = "0.11.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
 dependencies = [
  "base64 0.21.0",
  "bytes",
@@ -2607,17 +2675,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a"
 dependencies = [
  "base64 0.13.1",
- "bitflags 1.3.2",
+ "bitflags",
  "serde",
 ]
 
 [[package]]
 name = "rsa"
-version = "0.8.2"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55a77d189da1fee555ad95b7e50e7457d91c0e089ec68ca69ad2989413bbdab4"
+checksum = "3dd2017d3e6d67384f301f8b06fbf4567afc576430a61624d845eb04d2b30a72"
 dependencies = [
  "byteorder",
+ "const-oid",
  "digest",
  "num-bigint-dig",
  "num-integer",
@@ -2634,9 +2703,9 @@ dependencies = [
 
 [[package]]
 name = "rsa-magic-public-key"
-version = "0.7.0"
+version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a86cb93425d6e176cfa39d63e226289f13154173f18274fab609c71ff35ba3a0"
+checksum = "88ca6a6947c6fe6454c93c3bb65b92f9680e6f9e906e75e30631110f2227344c"
 dependencies = [
  "base64 0.21.0",
  "num-bigint-dig",
@@ -2703,16 +2772,16 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.36.11"
+version = "0.37.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "db4165c9963ab29e422d6c26fbc1d37f15bace6b2810221f9d925023480fcf0e"
+checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
  "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -2772,29 +2841,29 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 
 [[package]]
 name = "serde"
-version = "1.0.158"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "771d4d9c4163ee138805e12c710dd365e4f44be8be0503cb1bb9eb989425d9c9"
+checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.158"
+version = "1.0.160"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e801c1712f48475582b7696ac71e0ca34ebb30e09338425384269d9717c62cad"
+checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.15",
 ]
 
 [[package]]
 name = "serde_json"
-version = "1.0.94"
+version = "1.0.96"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea"
+checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
 dependencies = [
  "itoa",
  "ryu",
@@ -2876,9 +2945,9 @@ dependencies = [
 
 [[package]]
 name = "signature"
-version = "2.0.0"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d"
+checksum = "5e1788eed21689f9cf370582dfc467ef36ed9c707f073528ddafa8d83e3b8500"
 dependencies = [
  "digest",
  "rand_core",
@@ -2892,9 +2961,9 @@ checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de"
 
 [[package]]
 name = "sketches-ddsketch"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ceb945e54128e09c43d8e4f1277851bd5044c6fc540bbaa2ad888f60b3da9ae7"
+checksum = "68a406c1882ed7f29cd5e248c9848a80e7cb6ae0fea82346d2746f2f941c07e1"
 
 [[package]]
 name = "slab"
@@ -2945,9 +3014,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
 [[package]]
 name = "spki"
-version = "0.6.0"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
+checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e"
 dependencies = [
  "base64ct",
  "der",
@@ -3004,9 +3073,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.8"
+version = "2.0.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bcc02725fd69ab9f26eab07fad303e2497fad6fb9eba4f96c4d1687bdf704ad9"
+checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3063,7 +3132,7 @@ version = "0.9.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "303db260110c238e3af77bb9dff18bf7a5b5196f783059b0852aab75f91d5a16"
 dependencies = [
- "bitflags 1.3.2",
+ "bitflags",
  "bytes",
  "chrono",
  "derive_more",
@@ -3102,15 +3171,15 @@ dependencies = [
 
 [[package]]
 name = "tempfile"
-version = "3.4.0"
+version = "3.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af18f7ae1acd354b992402e9ec5864359d693cd8a79dcbef59f76891701c1e95"
+checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
 dependencies = [
  "cfg-if",
  "fastrand",
- "redox_syscall",
+ "redox_syscall 0.3.5",
  "rustix",
- "windows-sys 0.42.0",
+ "windows-sys 0.45.0",
 ]
 
 [[package]]
@@ -3124,15 +3193,6 @@ dependencies = [
  "utf-8",
 ]
 
-[[package]]
-name = "termcolor"
-version = "1.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6"
-dependencies = [
- "winapi-util",
-]
-
 [[package]]
 name = "thiserror"
 version = "1.0.40"
@@ -3150,7 +3210,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.8",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -3207,14 +3267,13 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.26.0"
+version = "1.28.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "03201d01c3c27a29c8a5cee5b55a93ddae1ccf6f08f65365c2c918f8c1b76f64"
+checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
 dependencies = [
  "autocfg",
  "bytes",
  "libc",
- "memchr",
  "mio",
  "parking_lot 0.12.1",
  "pin-project-lite",
@@ -3222,7 +3281,7 @@ dependencies = [
  "socket2",
  "tokio-macros",
  "tracing",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -3237,13 +3296,13 @@ dependencies = [
 
 [[package]]
 name = "tokio-macros"
-version = "1.8.2"
+version = "2.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
+checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -3259,9 +3318,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-stream"
-version = "0.1.12"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313"
+checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
 dependencies = [
  "futures-core",
  "pin-project-lite",
@@ -3270,9 +3329,9 @@ dependencies = [
 
 [[package]]
 name = "tokio-util"
-version = "0.7.7"
+version = "0.7.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2"
+checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
 dependencies = [
  "bytes",
  "futures-core",
@@ -3404,11 +3463,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
 
 [[package]]
 name = "tracing"
-version = "0.1.37"
+version = "0.1.38"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
+checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d"
 dependencies = [
- "cfg-if",
  "log",
  "pin-project-lite",
  "tracing-attributes",
@@ -3417,9 +3475,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a230d51c76e70c5ff8edae9085d7d7161803a871880406a6772639def50d059c"
+checksum = "e2def0ffabc0116481e14e82cf705fef814f5178171d445b6790137ff8a85a73"
 dependencies = [
  "actix-web",
  "pin-project",
@@ -3429,13 +3487,13 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.23"
+version = "0.1.24"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a"
+checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.15",
 ]
 
 [[package]]
@@ -3510,9 +3568,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-subscriber"
-version = "0.3.16"
+version = "0.3.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6176eae26dd70d0c919749377897b54a9276bd7061339665dd68777926b5a70"
+checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
 dependencies = [
  "matchers",
  "nu-ansi-term",
@@ -3599,10 +3657,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
 
 [[package]]
-name = "uuid"
-version = "1.3.0"
+name = "utf8parse"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79"
+checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+[[package]]
+name = "uuid"
+version = "1.3.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb"
 dependencies = [
  "getrandom",
  "serde",
@@ -3630,12 +3694,6 @@ dependencies = [
  "try-lock",
 ]
 
-[[package]]
-name = "wasi"
-version = "0.10.2+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
-
 [[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
@@ -3777,43 +3835,28 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
 
-[[package]]
-name = "winapi-util"
-version = "0.1.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
-dependencies = [
- "winapi",
-]
-
 [[package]]
 name = "winapi-x86_64-pc-windows-gnu"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "windows-sys"
-version = "0.42.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7"
-dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.45.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.42.2",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
+dependencies = [
+ "windows-targets 0.48.0",
 ]
 
 [[package]]
@@ -3822,13 +3865,28 @@ version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.42.2",
+ "windows_aarch64_msvc 0.42.2",
+ "windows_i686_gnu 0.42.2",
+ "windows_i686_msvc 0.42.2",
+ "windows_x86_64_gnu 0.42.2",
+ "windows_x86_64_gnullvm 0.42.2",
+ "windows_x86_64_msvc 0.42.2",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
+dependencies = [
+ "windows_aarch64_gnullvm 0.48.0",
+ "windows_aarch64_msvc 0.48.0",
+ "windows_i686_gnu 0.48.0",
+ "windows_i686_msvc 0.48.0",
+ "windows_x86_64_gnu 0.48.0",
+ "windows_x86_64_gnullvm 0.48.0",
+ "windows_x86_64_msvc 0.48.0",
 ]
 
 [[package]]
@@ -3837,36 +3895,72 @@ version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
 
+[[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
+
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
 
+[[package]]
+name = "windows_aarch64_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
+
 [[package]]
 name = "windows_i686_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
 
+[[package]]
+name = "windows_i686_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
+
 [[package]]
 name = "windows_i686_msvc"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
 
+[[package]]
+name = "windows_i686_msvc"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
+
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
 
+[[package]]
+name = "windows_x86_64_gnu"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
+
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.42.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
 
+[[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.48.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
+
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.42.2"
@@ -3874,10 +3968,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
 
 [[package]]
-name = "winnow"
-version = "0.4.0"
+name = "windows_x86_64_msvc"
+version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "deac0939bd6e4f24ab5919fbf751c97a8cfc8543bb083a305ed5c0c10bb241d1"
+checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
+
+[[package]]
+name = "winnow"
+version = "0.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
 dependencies = [
  "memchr",
 ]
@@ -3902,6 +4002,6 @@ dependencies = [
 
 [[package]]
 name = "zeroize"
-version = "1.5.7"
+version = "1.6.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c394b5bd0c6f669e7275d9c20aa90ae064cb22e75a1cad54e1b34088034b149f"
+checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9"
diff --git a/Cargo.toml b/Cargo.toml
index a06043d..6a18d6d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -42,20 +42,20 @@ dashmap = "5.1.0"
 dotenv = "0.15.0"
 futures-util = "0.3.17"
 lru = "0.10.0"
-metrics = "0.20.1"
-metrics-exporter-prometheus = { version = "0.11.0", default-features = false, features = [
+metrics = "0.21.0"
+metrics-exporter-prometheus = { version = "0.12.0", default-features = false, features = [
   "http-listener",
 ] }
-metrics-util = "0.14.0"
+metrics-util = "0.15.0"
 mime = "0.3.16"
 minify-html = "0.10.0"
 opentelemetry = { version = "0.18", features = ["rt-tokio"] }
 opentelemetry-otlp = "0.11"
 pin-project-lite = "0.2.9"
-quanta = "0.10.1"
+quanta = "0.11.0"
 rand = "0.8"
-rsa = { version = "0.8", features = ["sha2"] }
-rsa-magic-public-key = "0.7.0"
+rsa = { version = "0.9", features = ["sha2"] }
+rsa-magic-public-key = "0.8.0"
 rustls = "0.20.7"
 rustls-pemfile = "1.0.1"
 serde = { version = "1.0", features = ["derive"] }
@@ -83,7 +83,7 @@ tokio = { version = "1", features = ["macros", "sync"] }
 uuid = { version = "1", features = ["v4", "serde"] }
 
 [dependencies.background-jobs]
-version = "0.14.0"
+version = "0.15.0"
 default-features = false
 features = ["background-jobs-actix", "error-logging"]
 
diff --git a/src/middleware/verifier.rs b/src/middleware/verifier.rs
index 4e1e364..6528b83 100644
--- a/src/middleware/verifier.rs
+++ b/src/middleware/verifier.rs
@@ -129,7 +129,7 @@ async fn do_verify(
             let signature =
                 Signature::try_from(decoded.as_slice()).map_err(ErrorKind::ReadSignature)?;
 
-            let verifying_key = VerifyingKey::<Sha256>::new_with_prefix(public_key);
+            let verifying_key = VerifyingKey::<Sha256>::new(public_key);
             verifying_key
                 .verify(signing_string.as_bytes(), &signature)
                 .map_err(ErrorKind::VerifySignature)?;
diff --git a/src/requests.rs b/src/requests.rs
index 06c7450..0a2238e 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -12,7 +12,7 @@ use rand::thread_rng;
 use rsa::{
     pkcs1v15::SigningKey,
     sha2::{Digest, Sha256},
-    signature::RandomizedSigner,
+    signature::{RandomizedSigner, SignatureEncoding},
     RsaPrivateKey,
 };
 use std::{
@@ -417,9 +417,9 @@ struct Signer {
 
 impl Signer {
     fn sign(&self, signing_string: &str) -> Result<String, Error> {
-        let signing_key = SigningKey::<Sha256>::new_with_prefix(self.private_key.clone());
+        let signing_key = SigningKey::<Sha256>::new(self.private_key.clone());
         let signature =
             signing_key.try_sign_with_rng(&mut thread_rng(), signing_string.as_bytes())?;
-        Ok(STANDARD.encode(signature.as_ref()))
+        Ok(STANDARD.encode(signature.to_bytes().as_ref()))
     }
 }

From a9a47e8ee2ec3efd4d0bacd791a9623069fb079c Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Thu, 27 Apr 2023 19:54:15 -0500
Subject: [PATCH 75/87] Update flake

---
 relay.nix | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/relay.nix b/relay.nix
index 6362fbe..2ed523e 100644
--- a/relay.nix
+++ b/relay.nix
@@ -10,7 +10,7 @@ rustPlatform.buildRustPackage {
   pname = "relay";
   version = "0.4.0-beta.1";
   src = ./.;
-  cargoSha256 = "Kbicf3alz/QZJppBH4+dRhIf4extIONwBYnGF3TtqJ4=";
+  cargoSha256 = "hzNPI6ODQ208eGQ4xY3dZ+c5O1A3ozUF1emglv3ni/o=";
 
   PROTOC = "${protobuf}/bin/protoc";
   PROTOC_INCLUDE = "${protobuf}/include";

From d69a80ebe84c71908d40ff38b442b11a03497bef Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Wed, 24 May 2023 10:19:34 -0500
Subject: [PATCH 76/87] Update dependencies, not rustls

---
 Cargo.lock          | 502 +++++++++++++++++++++-----------------------
 Cargo.toml          |  12 +-
 src/routes/index.rs |   5 +-
 3 files changed, 245 insertions(+), 274 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index f094062..5273891 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -39,19 +39,19 @@ dependencies = [
 
 [[package]]
 name = "actix-codec"
-version = "0.5.0"
+version = "0.5.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "57a7559404a7f3573127aab53c08ce37a6c6a315c374a31070f3c91cd1b4a7fe"
+checksum = "617a8268e3537fe1d8c9ead925fca49ef6400927ee7bc26750e90ecee14ce4b8"
 dependencies = [
  "bitflags",
  "bytes",
  "futures-core",
  "futures-sink",
- "log",
  "memchr",
  "pin-project-lite",
  "tokio",
  "tokio-util",
+ "tracing",
 ]
 
 [[package]]
@@ -66,7 +66,7 @@ dependencies = [
  "actix-tls",
  "actix-utils",
  "ahash 0.8.3",
- "base64 0.21.0",
+ "base64 0.21.1",
  "bitflags",
  "brotli",
  "bytes",
@@ -170,7 +170,7 @@ dependencies = [
  "http",
  "log",
  "pin-project-lite",
- "tokio-rustls",
+ "tokio-rustls 0.23.4",
  "tokio-util",
  "webpki-roots",
 ]
@@ -315,9 +315,9 @@ dependencies = [
 
 [[package]]
 name = "anstream"
-version = "0.3.1"
+version = "0.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6342bd4f5a1205d7f41e94a41a901f5647c938cdfa96036338e8533c9d6c2450"
+checksum = "0ca84f3628370c59db74ee214b3263d58f9aadd9b4fe7e711fd87dc452b7f163"
 dependencies = [
  "anstyle",
  "anstyle-parse",
@@ -364,9 +364,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.70"
+version = "1.0.71"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
+checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "ap-relay"
@@ -381,7 +381,7 @@ dependencies = [
  "anyhow",
  "awc",
  "background-jobs",
- "base64 0.21.0",
+ "base64 0.21.1",
  "bcrypt",
  "clap",
  "config",
@@ -404,7 +404,7 @@ dependencies = [
  "rsa",
  "rsa-magic-public-key",
  "ructe",
- "rustls",
+ "rustls 0.20.8",
  "rustls-pemfile",
  "serde",
  "serde_json",
@@ -413,7 +413,7 @@ dependencies = [
  "thiserror",
  "time",
  "tokio",
- "toml 0.7.3",
+ "toml 0.7.4",
  "tracing",
  "tracing-actix-web",
  "tracing-awc",
@@ -463,7 +463,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -474,7 +474,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -496,7 +496,7 @@ dependencies = [
  "actix-tls",
  "actix-utils",
  "ahash 0.7.6",
- "base64 0.21.0",
+ "base64 0.21.1",
  "bytes",
  "cfg-if",
  "derive_more",
@@ -510,7 +510,7 @@ dependencies = [
  "percent-encoding",
  "pin-project-lite",
  "rand",
- "rustls",
+ "rustls 0.20.8",
  "serde",
  "serde_json",
  "serde_urlencoded",
@@ -519,9 +519,9 @@ dependencies = [
 
 [[package]]
 name = "axum"
-version = "0.6.17"
+version = "0.6.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b70caf9f1b0c045f7da350636435b775a9733adf2df56e8aa2a29210fbc335d4"
+checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39"
 dependencies = [
  "async-trait",
  "axum-core",
@@ -620,9 +620,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
 
 [[package]]
 name = "base64"
-version = "0.21.0"
+version = "0.21.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a"
+checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
 
 [[package]]
 name = "base64ct"
@@ -636,7 +636,7 @@ version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9df288bec72232f78c1ec5fe4e8f1d108aa0265476e93097593c803c8c02062a"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
  "blowfish",
  "getrandom",
  "subtle",
@@ -691,9 +691,9 @@ dependencies = [
 
 [[package]]
 name = "bumpalo"
-version = "3.12.1"
+version = "3.13.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8"
+checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1"
 
 [[package]]
 name = "bytecount"
@@ -756,9 +756,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.2.5"
+version = "4.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a1f23fa97e1d1641371b51f35535cb26959b8e27ab50d167a8b996b5bada819"
+checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -767,9 +767,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.2.5"
+version = "4.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fdc5d93c358224b4d6867ef1356d740de2303e9892edc06c5340daeccd96bab"
+checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990"
 dependencies = [
  "anstream",
  "anstyle",
@@ -780,21 +780,21 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.2.0"
+version = "4.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f9644cd56d6b87dbe899ef8b053e331c0637664e9e21a33dfcdc36093f5c5c4"
+checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b"
 dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "clap_lex"
-version = "0.4.1"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8a2dd5a6fe8c6e3502f568a6353e5273bbb15193ad9a89e457b9970798efbea1"
+checksum = "2da6da31387c7e4ef160ffab6d5e7f00c42626fe39aea70a7b0f1773f7dd6c1b"
 
 [[package]]
 name = "colorchoice"
@@ -823,21 +823,21 @@ dependencies = [
 
 [[package]]
 name = "console-api"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e57ff02e8ad8e06ab9731d5dc72dc23bef9200778eae1a89d555d8c42e5d4a86"
+checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e"
 dependencies = [
  "prost",
  "prost-types",
- "tonic",
+ "tonic 0.9.2",
  "tracing-core",
 ]
 
 [[package]]
 name = "console-subscriber"
-version = "0.1.8"
+version = "0.1.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22a3a81dfaf6b66bce5d159eddae701e3a002f194d378cbf7be5f053c281d9be"
+checksum = "57ab2224a0311582eb03adba4caaf18644f7b1f10a760803a803b9b605187fc7"
 dependencies = [
  "console-api",
  "crossbeam-channel",
@@ -851,7 +851,7 @@ dependencies = [
  "thread_local",
  "tokio",
  "tokio-stream",
- "tonic",
+ "tonic 0.9.2",
  "tracing",
  "tracing-core",
  "tracing-subscriber",
@@ -990,9 +990,9 @@ dependencies = [
 
 [[package]]
 name = "der"
-version = "0.7.5"
+version = "0.7.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05e58dffcdcc8ee7b22f0c1f71a69243d7c2d9ad87b5a14361f2424a1565c219"
+checksum = "56acb310e15652100da43d130af8d97b509e95af61aab1c5a7939ef24337ee17"
 dependencies = [
  "const-oid",
  "pem-rfc7468",
@@ -1014,9 +1014,9 @@ dependencies = [
 
 [[package]]
 name = "digest"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f"
+checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
 dependencies = [
  "block-buffer",
  "const-oid",
@@ -1111,17 +1111,11 @@ dependencies = [
  "instant",
 ]
 
-[[package]]
-name = "fixedbitset"
-version = "0.4.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
-
 [[package]]
 name = "flate2"
-version = "1.0.25"
+version = "1.0.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8a2db397cb1c8772f31494cb8917e48cd1e64f0fa7efac59fbd741a0a8ce841"
+checksum = "3b9429470923de8e8cbd4d2dc513535400b4b3fef0319fb5c4e1f520a7bef743"
 dependencies = [
  "crc32fast",
  "miniz_oxide",
@@ -1218,7 +1212,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -1283,9 +1277,9 @@ dependencies = [
 
 [[package]]
 name = "h2"
-version = "0.3.18"
+version = "0.3.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21"
+checksum = "d357c7ae988e7d2182f7d7871d0b963962420b0678b0997ce7de72001aeab782"
 dependencies = [
  "bytes",
  "fnv",
@@ -1462,15 +1456,15 @@ dependencies = [
 
 [[package]]
 name = "hyper-rustls"
-version = "0.23.2"
+version = "0.24.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1788965e61b367cd03a62950836d5cd41560c3577d90e40e0819373194d1661c"
+checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7"
 dependencies = [
  "http",
  "hyper",
- "rustls",
+ "rustls 0.21.1",
  "tokio",
- "tokio-rustls",
+ "tokio-rustls 0.24.0",
 ]
 
 [[package]]
@@ -1531,9 +1525,9 @@ dependencies = [
 
 [[package]]
 name = "io-lifetimes"
-version = "1.0.10"
+version = "1.0.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220"
+checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 dependencies = [
  "hermit-abi 0.3.1",
  "libc",
@@ -1594,9 +1588,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "js-sys"
-version = "0.3.61"
+version = "0.3.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730"
+checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -1629,15 +1623,15 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.142"
+version = "0.2.144"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317"
+checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
 
 [[package]]
 name = "libm"
-version = "0.2.6"
+version = "0.2.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb"
+checksum = "f7012b1bbb0719e1097c47611d3898568c546d597c2e74d66f6087edd5233ff4"
 
 [[package]]
 name = "linked-hash-map"
@@ -1647,9 +1641,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
 
 [[package]]
 name = "linux-raw-sys"
-version = "0.3.5"
+version = "0.3.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e8776872cdc2f073ccaab02e336fa321328c1e02646ebcb9d2108d0baab480d"
+checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519"
 
 [[package]]
 name = "local-channel"
@@ -1781,10 +1775,11 @@ dependencies = [
 
 [[package]]
 name = "metrics-exporter-prometheus"
-version = "0.12.0"
+version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5142a593c2be0cf5c2ac5b22ec7a4f74477b851efb6238236af26c6b5ca6e98e"
+checksum = "8a4964177ddfdab1e3a2b37aec7cf320e14169abb0ed73999f558136409178d5"
 dependencies = [
+ "base64 0.21.1",
  "hyper",
  "indexmap",
  "ipnet",
@@ -1803,7 +1798,7 @@ checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -1843,9 +1838,9 @@ dependencies = [
 
 [[package]]
 name = "minify-html"
-version = "0.10.8"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7754d4669873379ea6a8a5b56e406eb83de713af8a791517ef35a0c832b1e7d5"
+checksum = "fc4d9147754a49e80557df835eb59e743eab1bf75410a134f55dc4b9dbb692ad"
 dependencies = [
  "aho-corasick 0.7.20",
  "css-minify",
@@ -1873,9 +1868,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
 
 [[package]]
 name = "miniz_oxide"
-version = "0.6.2"
+version = "0.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa"
+checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
 dependencies = [
  "adler",
 ]
@@ -1892,12 +1887,6 @@ dependencies = [
  "windows-sys 0.45.0",
 ]
 
-[[package]]
-name = "multimap"
-version = "0.8.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5ce46fe64a9d73be07dcbe690a38ce1b293be448fd8ce1e6c1b8062c9f72c6a"
-
 [[package]]
 name = "never"
 version = "0.1.0"
@@ -2029,9 +2018,9 @@ checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
 
 [[package]]
 name = "opentelemetry"
-version = "0.18.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "69d6c3d7288a106c0a363e4b0e8d308058d56902adefb16f4936f417ffef086e"
+checksum = "5f4b8347cc26099d3aeee044065ecc3ae11469796b4d65d065a23a584ed92a6f"
 dependencies = [
  "opentelemetry_api",
  "opentelemetry_sdk",
@@ -2039,9 +2028,9 @@ dependencies = [
 
 [[package]]
 name = "opentelemetry-otlp"
-version = "0.11.0"
+version = "0.12.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1c928609d087790fc936a1067bdc310ae702bdf3b090c3f281b713622c8bbde"
+checksum = "8af72d59a4484654ea8eb183fea5ae4eb6a41d7ac3e3bae5f4d2a282a3a7d3ca"
 dependencies = [
  "async-trait",
  "futures",
@@ -2052,44 +2041,43 @@ dependencies = [
  "prost",
  "thiserror",
  "tokio",
- "tonic",
+ "tonic 0.8.3",
 ]
 
 [[package]]
 name = "opentelemetry-proto"
-version = "0.1.0"
+version = "0.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61a2f56df5574508dd86aaca016c917489e589ece4141df1b5e349af8d66c28"
+checksum = "045f8eea8c0fa19f7d48e7bc3128a39c2e5c533d5c61298c548dfefc1064474c"
 dependencies = [
  "futures",
  "futures-util",
  "opentelemetry",
  "prost",
- "tonic",
- "tonic-build",
+ "tonic 0.8.3",
 ]
 
 [[package]]
 name = "opentelemetry_api"
-version = "0.18.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c24f96e21e7acc813c7a8394ee94978929db2bcc46cf6b5014fc612bf7760c22"
+checksum = "ed41783a5bf567688eb38372f2b7a8530f5a607a4b49d38dd7573236c23ca7e2"
 dependencies = [
  "fnv",
  "futures-channel",
  "futures-util",
  "indexmap",
- "js-sys",
  "once_cell",
  "pin-project-lite",
  "thiserror",
+ "urlencoding",
 ]
 
 [[package]]
 name = "opentelemetry_sdk"
-version = "0.18.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ca41c4933371b61c2a2f214bf16931499af4ec90543604ec828f7a625c09113"
+checksum = "8b3a2a91fdbfdd4d212c0dcc2ab540de2c2bcbbd90be17de7a7daf8822d010c1"
 dependencies = [
  "async-trait",
  "crossbeam-channel",
@@ -2162,7 +2150,7 @@ dependencies = [
  "cfg-if",
  "instant",
  "libc",
- "redox_syscall 0.2.16",
+ "redox_syscall",
  "smallvec",
  "winapi",
 ]
@@ -2175,7 +2163,7 @@ checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall 0.2.16",
+ "redox_syscall",
  "smallvec",
  "windows-sys 0.45.0",
 ]
@@ -2248,7 +2236,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -2262,16 +2250,6 @@ dependencies = [
  "sha2",
 ]
 
-[[package]]
-name = "petgraph"
-version = "0.6.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4"
-dependencies = [
- "fixedbitset",
- "indexmap",
-]
-
 [[package]]
 name = "phf"
 version = "0.10.1"
@@ -2312,22 +2290,22 @@ dependencies = [
 
 [[package]]
 name = "pin-project"
-version = "1.0.12"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc"
+checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.0.12"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55"
+checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -2365,9 +2343,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "1.2.0"
+version = "1.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f602a0d1e09a48e4f8e8b4d4042e32807c3676da31f2ecabeac9f96226ec6c45"
+checksum = "dc59d1bcc64fc5d021d67521f818db868368028108d37f0e98d74e33f68297b5"
 
 [[package]]
 name = "ppv-lite86"
@@ -2381,16 +2359,6 @@ version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
 
-[[package]]
-name = "prettyplease"
-version = "0.1.25"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c8646e95016a7a6c4adea95bafa8a16baab64b583356217f2c85db4a39d9a86"
-dependencies = [
- "proc-macro2",
- "syn 1.0.109",
-]
-
 [[package]]
 name = "proc-macro-error"
 version = "1.0.4"
@@ -2417,9 +2385,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.56"
+version = "1.0.58"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435"
+checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
 dependencies = [
  "unicode-ident",
 ]
@@ -2434,28 +2402,6 @@ dependencies = [
  "prost-derive",
 ]
 
-[[package]]
-name = "prost-build"
-version = "0.11.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "119533552c9a7ffacc21e099c24a0ac8bb19c2a2a3f363de84cd9b844feab270"
-dependencies = [
- "bytes",
- "heck",
- "itertools 0.10.5",
- "lazy_static",
- "log",
- "multimap",
- "petgraph",
- "prettyplease",
- "prost",
- "prost-types",
- "regex",
- "syn 1.0.109",
- "tempfile",
- "which",
-]
-
 [[package]]
 name = "prost-derive"
 version = "0.11.9"
@@ -2496,9 +2442,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.27"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
 dependencies = [
  "proc-macro2",
 ]
@@ -2570,24 +2516,15 @@ dependencies = [
  "bitflags",
 ]
 
-[[package]]
-name = "redox_syscall"
-version = "0.3.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
-dependencies = [
- "bitflags",
-]
-
 [[package]]
 name = "regex"
-version = "1.8.1"
+version = "1.8.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370"
+checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
 dependencies = [
  "aho-corasick 1.0.1",
  "memchr",
- "regex-syntax 0.7.1",
+ "regex-syntax 0.7.2",
 ]
 
 [[package]]
@@ -2607,17 +2544,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "regex-syntax"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c"
+checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
 
 [[package]]
 name = "reqwest"
-version = "0.11.16"
+version = "0.11.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254"
+checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
  "bytes",
  "encoding_rs",
  "futures-core",
@@ -2635,13 +2572,13 @@ dependencies = [
  "once_cell",
  "percent-encoding",
  "pin-project-lite",
- "rustls",
+ "rustls 0.21.1",
  "rustls-pemfile",
  "serde",
  "serde_json",
  "serde_urlencoded",
  "tokio",
- "tokio-rustls",
+ "tokio-rustls 0.24.0",
  "tokio-util",
  "tower-service",
  "url",
@@ -2681,9 +2618,9 @@ dependencies = [
 
 [[package]]
 name = "rsa"
-version = "0.9.0"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dd2017d3e6d67384f301f8b06fbf4567afc576430a61624d845eb04d2b30a72"
+checksum = "6ab43bb47d23c1a631b4b680199a45255dce26fa9ab2fa902581f624ff13e6a8"
 dependencies = [
  "byteorder",
  "const-oid",
@@ -2697,6 +2634,7 @@ dependencies = [
  "rand_core",
  "sha2",
  "signature",
+ "spki",
  "subtle",
  "zeroize",
 ]
@@ -2707,7 +2645,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88ca6a6947c6fe6454c93c3bb65b92f9680e6f9e906e75e30631110f2227344c"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
  "num-bigint-dig",
  "rsa",
  "thiserror",
@@ -2736,7 +2674,7 @@ version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "79c86c1631418815c5947a34be5872806586c65398754ec91cc2df35a8e26ba8"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
  "bytecount",
  "itertools 0.10.5",
  "md5",
@@ -2772,9 +2710,9 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.37.15"
+version = "0.37.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a0661814f891c57c930a610266415528da53c4933e6dea5fb350cbfe048a9ece"
+checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
 dependencies = [
  "bitflags",
  "errno",
@@ -2796,13 +2734,35 @@ dependencies = [
  "webpki",
 ]
 
+[[package]]
+name = "rustls"
+version = "0.21.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e"
+dependencies = [
+ "log",
+ "ring",
+ "rustls-webpki",
+ "sct",
+]
+
 [[package]]
 name = "rustls-pemfile"
 version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
 dependencies = [
- "base64 0.21.0",
+ "base64 0.21.1",
+]
+
+[[package]]
+name = "rustls-webpki"
+version = "0.100.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d6207cd5ed3d8dca7816f8f3725513a34609c0c765bf652b8c3cb4cfd87db46b"
+dependencies = [
+ "ring",
+ "untrusted",
 ]
 
 [[package]]
@@ -2841,22 +2801,22 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 
 [[package]]
 name = "serde"
-version = "1.0.160"
+version = "1.0.163"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c"
+checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.160"
+version = "1.0.163"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df"
+checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -2872,9 +2832,9 @@ dependencies = [
 
 [[package]]
 name = "serde_spanned"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0efd8caf556a6cebd3b285caf480045fcc1ac04f6bd786b09a6f11af30c4fcf4"
+checksum = "93107647184f6027e3b7dcb2e11034cf95ffa1e3a682c67951963ac69c1c007d"
 dependencies = [
  "serde",
 ]
@@ -3014,9 +2974,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
 
 [[package]]
 name = "spki"
-version = "0.7.1"
+version = "0.7.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37a5be806ab6f127c3da44b7378837ebf01dadca8510a0e572460216b228bd0e"
+checksum = "9d1e996ef02c474957d681f1b05213dfb0abab947b446a62d37770b23500184a"
 dependencies = [
  "base64ct",
  "der",
@@ -3073,9 +3033,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3169,19 +3129,6 @@ dependencies = [
  "syn 1.0.109",
 ]
 
-[[package]]
-name = "tempfile"
-version = "3.5.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998"
-dependencies = [
- "cfg-if",
- "fastrand",
- "redox_syscall 0.3.5",
- "rustix",
- "windows-sys 0.45.0",
-]
-
 [[package]]
 name = "tendril"
 version = "0.4.3"
@@ -3210,7 +3157,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -3225,9 +3172,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.20"
+version = "0.3.21"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd0cbfecb4d19b5ea75bb31ad904eb5b9fa13f21079c3b92017ebdf4999a5890"
+checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
 dependencies = [
  "itoa",
  "serde",
@@ -3237,15 +3184,15 @@ dependencies = [
 
 [[package]]
 name = "time-core"
-version = "0.1.0"
+version = "0.1.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2e153e1f1acaef8acc537e68b44906d2db6436e2b35ac2c6b42640fff91f00fd"
+checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
 
 [[package]]
 name = "time-macros"
-version = "0.2.8"
+version = "0.2.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd80a657e71da814b8e5d60d3374fc6d35045062245d80224748ae522dd76f36"
+checksum = "372950940a5f07bf38dbe211d7283c9e6d7327df53794992d293e534c733d09b"
 dependencies = [
  "time-core",
 ]
@@ -3267,9 +3214,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.28.0"
+version = "1.28.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
+checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3302,7 +3249,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
@@ -3311,11 +3258,21 @@ version = "0.23.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
 dependencies = [
- "rustls",
+ "rustls 0.20.8",
  "tokio",
  "webpki",
 ]
 
+[[package]]
+name = "tokio-rustls"
+version = "0.24.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5"
+dependencies = [
+ "rustls 0.21.1",
+ "tokio",
+]
+
 [[package]]
 name = "tokio-stream"
 version = "0.1.14"
@@ -3352,9 +3309,9 @@ dependencies = [
 
 [[package]]
 name = "toml"
-version = "0.7.3"
+version = "0.7.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b403acf6f2bb0859c93c7f0d967cb4a75a7ac552100f9322faf64dc047669b21"
+checksum = "d6135d499e69981f9ff0ef2167955a5333c35e36f6937d382974566b3d5b94ec"
 dependencies = [
  "serde",
  "serde_spanned",
@@ -3364,18 +3321,18 @@ dependencies = [
 
 [[package]]
 name = "toml_datetime"
-version = "0.6.1"
+version = "0.6.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3ab8ed2edee10b50132aed5f331333428b011c99402b5a534154ed15746f9622"
+checksum = "5a76a9312f5ba4c2dec6b9161fdf25d87ad8a09256ccea5a556fef03c706a10f"
 dependencies = [
  "serde",
 ]
 
 [[package]]
 name = "toml_edit"
-version = "0.19.8"
+version = "0.19.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "239410c8609e8125456927e6707163a3b1fdb40561e4b803bc041f466ccfdc13"
+checksum = "2380d56e8670370eee6566b0bfd4265f65b3f432e8c6d85623f728d4fa31f739"
 dependencies = [
  "indexmap",
  "serde",
@@ -3417,16 +3374,31 @@ dependencies = [
 ]
 
 [[package]]
-name = "tonic-build"
-version = "0.8.4"
+name = "tonic"
+version = "0.9.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bf5e9b9c0f7e0a7c027dcfaba7b2c60816c7049171f679d99ee2ff65d0de8c4"
+checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a"
 dependencies = [
- "prettyplease",
- "proc-macro2",
- "prost-build",
- "quote",
- "syn 1.0.109",
+ "async-trait",
+ "axum",
+ "base64 0.21.1",
+ "bytes",
+ "futures-core",
+ "futures-util",
+ "h2",
+ "http",
+ "http-body",
+ "hyper",
+ "hyper-timeout",
+ "percent-encoding",
+ "pin-project",
+ "prost",
+ "tokio",
+ "tokio-stream",
+ "tower",
+ "tower-layer",
+ "tower-service",
+ "tracing",
 ]
 
 [[package]]
@@ -3463,10 +3435,11 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
 
 [[package]]
 name = "tracing"
-version = "0.1.38"
+version = "0.1.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9cf6a813d3f40c88b0b6b6f29a5c95c6cdbf97c1f9cc53fb820200f5ad814d"
+checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8"
 dependencies = [
+ "cfg-if",
  "log",
  "pin-project-lite",
  "tracing-attributes",
@@ -3475,9 +3448,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-actix-web"
-version = "0.7.4"
+version = "0.7.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2def0ffabc0116481e14e82cf705fef814f5178171d445b6790137ff8a85a73"
+checksum = "ce52ffaf2d544e317d3bef63f49a6a22022866505fa4840a4339b1756834a2a9"
 dependencies = [
  "actix-web",
  "pin-project",
@@ -3493,14 +3466,14 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.15",
+ "syn 2.0.16",
 ]
 
 [[package]]
 name = "tracing-awc"
-version = "0.1.6"
+version = "0.1.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ab0b57d9e4b25f3d5f17d705c11c13c333b26dc062c02a9dedfe6a26f750a99e"
+checksum = "eaa1a68fce4d1a7fad459f81ddcafbdd7c6f6bcda5c7e07d5f42db637931fac7"
 dependencies = [
  "actix-http",
  "actix-service",
@@ -3513,9 +3486,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-core"
-version = "0.1.30"
+version = "0.1.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a"
+checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a"
 dependencies = [
  "once_cell",
  "valuable",
@@ -3554,9 +3527,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-opentelemetry"
-version = "0.18.0"
+version = "0.19.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "21ebb87a95ea13271332df069020513ab70bdb5637ca42d6e492dc3bbbad48de"
+checksum = "00a39dcf9bfc1742fa4d6215253b33a6e474be78275884c216fc2a06267b3600"
 dependencies = [
  "once_cell",
  "opentelemetry",
@@ -3650,6 +3623,12 @@ dependencies = [
  "serde",
 ]
 
+[[package]]
+name = "urlencoding"
+version = "2.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e8db7427f936968176eaa7cdf81b7f98b980b18495ec28f1b5791ac3bfe3eea9"
+
 [[package]]
 name = "utf-8"
 version = "0.7.6"
@@ -3664,9 +3643,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 [[package]]
 name = "uuid"
-version = "1.3.1"
+version = "1.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb"
+checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
 dependencies = [
  "getrandom",
  "serde",
@@ -3702,9 +3681,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.84"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b"
+checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -3712,24 +3691,24 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.84"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9"
+checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
 dependencies = [
  "bumpalo",
  "log",
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.16",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.34"
+version = "0.4.36"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454"
+checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -3739,9 +3718,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.84"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5"
+checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -3749,22 +3728,22 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.84"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6"
+checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 1.0.109",
+ "syn 2.0.16",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.84"
+version = "0.2.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d"
+checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
 
 [[package]]
 name = "wasm-streams"
@@ -3781,9 +3760,9 @@ dependencies = [
 
 [[package]]
 name = "web-sys"
-version = "0.3.61"
+version = "0.3.63"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97"
+checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -3808,17 +3787,6 @@ dependencies = [
  "webpki",
 ]
 
-[[package]]
-name = "which"
-version = "4.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269"
-dependencies = [
- "either",
- "libc",
- "once_cell",
-]
-
 [[package]]
 name = "winapi"
 version = "0.3.9"
@@ -3975,9 +3943,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
 
 [[package]]
 name = "winnow"
-version = "0.4.1"
+version = "0.4.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ae8970b36c66498d8ff1d66685dc86b91b29db0c7739899012f63a63814b4b28"
+checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
 dependencies = [
  "memchr",
 ]
diff --git a/Cargo.toml b/Cargo.toml
index 6a18d6d..2609f47 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -48,9 +48,9 @@ metrics-exporter-prometheus = { version = "0.12.0", default-features = false, fe
 ] }
 metrics-util = "0.15.0"
 mime = "0.3.16"
-minify-html = "0.10.0"
-opentelemetry = { version = "0.18", features = ["rt-tokio"] }
-opentelemetry-otlp = "0.11"
+minify-html = "0.11.0"
+opentelemetry = { version = "0.19", features = ["rt-tokio"] }
+opentelemetry-otlp = "0.12"
 pin-project-lite = "0.2.9"
 quanta = "0.11.0"
 rand = "0.8"
@@ -69,11 +69,11 @@ teloxide = { version = "0.12.0", default-features = false, features = [
 thiserror = "1.0"
 time = { version = "0.3.17", features = ["serde"] }
 tracing = "0.1"
-tracing-awc = "0.1.6"
+tracing-awc = "0.1.7"
 tracing-error = "0.2"
 tracing-futures = "0.2"
 tracing-log = "0.1"
-tracing-opentelemetry = "0.18"
+tracing-opentelemetry = "0.19"
 tracing-subscriber = { version = "0.3", features = [
   "ansi",
   "env-filter",
@@ -93,7 +93,7 @@ default-features = false
 features = ["client", "server", "sha-2"]
 
 [dependencies.tracing-actix-web]
-version = "0.7.0"
+version = "0.7.5"
 
 [build-dependencies]
 anyhow = "1.0"
diff --git a/src/routes/index.rs b/src/routes/index.rs
index d1b4b21..cdd2a91 100644
--- a/src/routes/index.rs
+++ b/src/routes/index.rs
@@ -14,8 +14,11 @@ const MINIFY_CONFIG: minify_html::Cfg = minify_html::Cfg {
     keep_html_and_head_opening_tags: false,
     keep_spaces_between_attributes: true,
     keep_comments: false,
-    minify_js: true,
     minify_css: true,
+    minify_css_level_1: true,
+    minify_css_level_2: false,
+    minify_css_level_3: false,
+    minify_js: true,
     remove_bangs: true,
     remove_processing_instructions: true,
 };

From 5fa1d4983a2680e4b2cd15377cb79c9b2695f031 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 3 Jun 2023 13:10:19 -0500
Subject: [PATCH 77/87] Update nix

---
 flake.lock | 30 ++++++++++++++++++++++++------
 relay.nix  |  4 ++--
 2 files changed, 26 insertions(+), 8 deletions(-)

diff --git a/flake.lock b/flake.lock
index 55f41fb..2ae085e 100644
--- a/flake.lock
+++ b/flake.lock
@@ -1,12 +1,15 @@
 {
   "nodes": {
     "flake-utils": {
+      "inputs": {
+        "systems": "systems"
+      },
       "locked": {
-        "lastModified": 1678901627,
-        "narHash": "sha256-U02riOqrKKzwjsxc/400XnElV+UtPUQWpANPlyazjH0=",
+        "lastModified": 1685518550,
+        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "93a2b84fc4b70d9e089d029deacc3583435c2ed6",
+        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
         "type": "github"
       },
       "original": {
@@ -17,11 +20,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1679437018,
-        "narHash": "sha256-vOuiDPLHSEo/7NkiWtxpHpHgoXoNmrm+wkXZ6a072Fc=",
+        "lastModified": 1685655444,
+        "narHash": "sha256-6EujQNAeaUkWvpEZZcVF8qSfQrNVWFNNGbUJxv/A5a8=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "19cf008bb18e47b6e3b4e16e32a9a4bdd4b45f7e",
+        "rev": "e635192892f5abbc2289eaac3a73cdb249abaefd",
         "type": "github"
       },
       "original": {
@@ -36,6 +39,21 @@
         "flake-utils": "flake-utils",
         "nixpkgs": "nixpkgs"
       }
+    },
+    "systems": {
+      "locked": {
+        "lastModified": 1681028828,
+        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
+        "owner": "nix-systems",
+        "repo": "default",
+        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
+        "type": "github"
+      },
+      "original": {
+        "owner": "nix-systems",
+        "repo": "default",
+        "type": "github"
+      }
     }
   },
   "root": "root",
diff --git a/relay.nix b/relay.nix
index 2ed523e..03db9d5 100644
--- a/relay.nix
+++ b/relay.nix
@@ -8,9 +8,9 @@
 
 rustPlatform.buildRustPackage {
   pname = "relay";
-  version = "0.4.0-beta.1";
+  version = "0.3.82";
   src = ./.;
-  cargoSha256 = "hzNPI6ODQ208eGQ4xY3dZ+c5O1A3ozUF1emglv3ni/o=";
+  cargoLock.lockFile = ./Cargo.lock;
 
   PROTOC = "${protobuf}/bin/protoc";
   PROTOC_INCLUDE = "${protobuf}/include";

From 9b4f6b47a61ddaf8f2325ada0656f9e715bb431a Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Sat, 3 Jun 2023 13:13:37 -0500
Subject: [PATCH 78/87] cargo update

---
 Cargo.lock | 123 +++++++++++++++++++++++++++--------------------------
 1 file changed, 63 insertions(+), 60 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 5273891..f1e7e80 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -66,7 +66,7 @@ dependencies = [
  "actix-tls",
  "actix-utils",
  "ahash 0.8.3",
- "base64 0.21.1",
+ "base64 0.21.2",
  "bitflags",
  "brotli",
  "bytes",
@@ -313,6 +313,12 @@ dependencies = [
  "url",
 ]
 
+[[package]]
+name = "android-tzdata"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
+
 [[package]]
 name = "anstream"
 version = "0.3.2"
@@ -381,7 +387,7 @@ dependencies = [
  "anyhow",
  "awc",
  "background-jobs",
- "base64 0.21.1",
+ "base64 0.21.2",
  "bcrypt",
  "clap",
  "config",
@@ -463,7 +469,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -474,7 +480,7 @@ checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -496,7 +502,7 @@ dependencies = [
  "actix-tls",
  "actix-utils",
  "ahash 0.7.6",
- "base64 0.21.1",
+ "base64 0.21.2",
  "bytes",
  "cfg-if",
  "derive_more",
@@ -620,9 +626,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
 
 [[package]]
 name = "base64"
-version = "0.21.1"
+version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3f1e31e207a6b8fb791a38ea3105e6cb541f55e4d029902d3039a4ad07cc4105"
+checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d"
 
 [[package]]
 name = "base64ct"
@@ -636,7 +642,7 @@ version = "0.14.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9df288bec72232f78c1ec5fe4e8f1d108aa0265476e93097593c803c8c02062a"
 dependencies = [
- "base64 0.21.1",
+ "base64 0.21.2",
  "blowfish",
  "getrandom",
  "subtle",
@@ -736,11 +742,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
 name = "chrono"
-version = "0.4.24"
+version = "0.4.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4e3c5919066adf22df73762e50cffcde3a758f2a848b113b586d1f86728b673b"
+checksum = "ec837a71355b28f6556dbd569b37b3f363091c0bd4b2e735674521b4c5fd9bc5"
 dependencies = [
- "num-integer",
+ "android-tzdata",
  "num-traits",
 ]
 
@@ -756,9 +762,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.3.0"
+version = "4.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93aae7a4192245f70fe75dd9157fc7b4a5bf53e88d30bd4396f7d8f9284d5acc"
+checksum = "b4ed2379f8603fa2b7509891660e802b88c70a79a6427a70abb5968054de2c28"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -767,9 +773,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.3.0"
+version = "4.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4f423e341edefb78c9caba2d9c7f7687d0e72e89df3ce3394554754393ac3990"
+checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980"
 dependencies = [
  "anstream",
  "anstyle",
@@ -780,14 +786,14 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.3.0"
+version = "4.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "191d9573962933b4027f932c600cd252ce27a8ad5979418fe78e43c07996f27b"
+checksum = "59e9ef9a08ee1c0e1f2e162121665ac45ac3783b0f897db7244ae75ad9a8f65b"
 dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -1212,7 +1218,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -1675,12 +1681,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.17"
+version = "0.4.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
-dependencies = [
- "cfg-if",
-]
+checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
 
 [[package]]
 name = "lru"
@@ -1779,7 +1782,7 @@ version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8a4964177ddfdab1e3a2b37aec7cf320e14169abb0ed73999f558136409178d5"
 dependencies = [
- "base64 0.21.1",
+ "base64 0.21.2",
  "hyper",
  "indexmap",
  "ipnet",
@@ -1798,7 +1801,7 @@ checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -1877,14 +1880,14 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.8.6"
+version = "0.8.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9"
+checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2"
 dependencies = [
  "libc",
  "log",
  "wasi",
- "windows-sys 0.45.0",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -2012,9 +2015,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.17.1"
+version = "1.17.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3"
+checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
 
 [[package]]
 name = "opentelemetry"
@@ -2236,7 +2239,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -2305,7 +2308,7 @@ checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -2343,9 +2346,9 @@ dependencies = [
 
 [[package]]
 name = "portable-atomic"
-version = "1.3.2"
+version = "1.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dc59d1bcc64fc5d021d67521f818db868368028108d37f0e98d74e33f68297b5"
+checksum = "767eb9f07d4a5ebcb39bbf2d452058a93c011373abf6832e24194a1c3f004794"
 
 [[package]]
 name = "ppv-lite86"
@@ -2385,9 +2388,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.58"
+version = "1.0.59"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa1fb82fc0c281dd9671101b66b771ebbe1eaf967b96ac8740dcba4b70005ca8"
+checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
 dependencies = [
  "unicode-ident",
 ]
@@ -2426,9 +2429,9 @@ dependencies = [
 
 [[package]]
 name = "quanta"
-version = "0.11.0"
+version = "0.11.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8cc73c42f9314c4bdce450c77e6f09ecbddefbeddb1b5979ded332a3913ded33"
+checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab"
 dependencies = [
  "crossbeam-utils",
  "libc",
@@ -2442,9 +2445,9 @@ dependencies = [
 
 [[package]]
 name = "quote"
-version = "1.0.27"
+version = "1.0.28"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f4f29d145265ec1c483c7c654450edde0bfe043d3938d6972630663356d9500"
+checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488"
 dependencies = [
  "proc-macro2",
 ]
@@ -2518,9 +2521,9 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.8.2"
+version = "1.8.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d1a59b5d8e97dee33696bf13c5ba8ab85341c002922fba050069326b9c498974"
+checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
 dependencies = [
  "aho-corasick 1.0.1",
  "memchr",
@@ -2554,7 +2557,7 @@ version = "0.11.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "cde824a14b7c14f85caff81225f411faacc04a2013f41670f41443742b1c1c55"
 dependencies = [
- "base64 0.21.1",
+ "base64 0.21.2",
  "bytes",
  "encoding_rs",
  "futures-core",
@@ -2645,7 +2648,7 @@ version = "0.8.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "88ca6a6947c6fe6454c93c3bb65b92f9680e6f9e906e75e30631110f2227344c"
 dependencies = [
- "base64 0.21.1",
+ "base64 0.21.2",
  "num-bigint-dig",
  "rsa",
  "thiserror",
@@ -2674,7 +2677,7 @@ version = "0.16.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "79c86c1631418815c5947a34be5872806586c65398754ec91cc2df35a8e26ba8"
 dependencies = [
- "base64 0.21.1",
+ "base64 0.21.2",
  "bytecount",
  "itertools 0.10.5",
  "md5",
@@ -2752,7 +2755,7 @@ version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b"
 dependencies = [
- "base64 0.21.1",
+ "base64 0.21.2",
 ]
 
 [[package]]
@@ -2816,7 +2819,7 @@ checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -3033,9 +3036,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.16"
+version = "2.0.18"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a6f671d4b5ffdb8eadec19c0ae67fe2639df8684bd7bc4b83d986b8db549cf01"
+checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3157,7 +3160,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -3214,9 +3217,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
 
 [[package]]
 name = "tokio"
-version = "1.28.1"
+version = "1.28.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0aa32867d44e6f2ce3385e89dceb990188b8bb0fb25b0cf576647a6f98ac5105"
+checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2"
 dependencies = [
  "autocfg",
  "bytes",
@@ -3249,7 +3252,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -3381,7 +3384,7 @@ checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a"
 dependencies = [
  "async-trait",
  "axum",
- "base64 0.21.1",
+ "base64 0.21.2",
  "bytes",
  "futures-core",
  "futures-util",
@@ -3466,7 +3469,7 @@ checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
 ]
 
 [[package]]
@@ -3592,9 +3595,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460"
 
 [[package]]
 name = "unicode-ident"
-version = "1.0.8"
+version = "1.0.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4"
+checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0"
 
 [[package]]
 name = "unicode-normalization"
@@ -3700,7 +3703,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
  "wasm-bindgen-shared",
 ]
 
@@ -3734,7 +3737,7 @@ checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.16",
+ "syn 2.0.18",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]

From 4b71e56f31d0df868ab381547c27bacddf41f4a4 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 13:34:21 -0500
Subject: [PATCH 79/87] Update nixpkgs

---
 flake.lock | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/flake.lock b/flake.lock
index 2ae085e..0cb587b 100644
--- a/flake.lock
+++ b/flake.lock
@@ -5,11 +5,11 @@
         "systems": "systems"
       },
       "locked": {
-        "lastModified": 1685518550,
-        "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
+        "lastModified": 1687171271,
+        "narHash": "sha256-BJlq+ozK2B1sJDQXS3tzJM5a+oVZmi1q0FlBK/Xqv7M=",
         "owner": "numtide",
         "repo": "flake-utils",
-        "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
+        "rev": "abfb11bd1aec8ced1c9bb9adfe68018230f4fb3c",
         "type": "github"
       },
       "original": {
@@ -20,11 +20,11 @@
     },
     "nixpkgs": {
       "locked": {
-        "lastModified": 1685655444,
-        "narHash": "sha256-6EujQNAeaUkWvpEZZcVF8qSfQrNVWFNNGbUJxv/A5a8=",
+        "lastModified": 1687412861,
+        "narHash": "sha256-Z/g0wbL68C+mSGerYS2quv9FXQ1RRP082cAC0Bh4vcs=",
         "owner": "NixOS",
         "repo": "nixpkgs",
-        "rev": "e635192892f5abbc2289eaac3a73cdb249abaefd",
+        "rev": "e603dc5f061ca1d8a19b3ede6a8cf9c9fcba6cdc",
         "type": "github"
       },
       "original": {

From 18ff2864a0b15871c46e5d447bdc10edba96f4b6 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 13:34:39 -0500
Subject: [PATCH 80/87] Update dependencies (minor & point)

---
 Cargo.lock | 316 ++++++++++++++++++++++-------------------------------
 1 file changed, 129 insertions(+), 187 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index f1e7e80..9db86e3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -278,9 +278,9 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "1.0.1"
+version = "1.0.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04"
+checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
 dependencies = [
  "memchr",
 ]
@@ -336,15 +336,15 @@ dependencies = [
 
 [[package]]
 name = "anstyle"
-version = "1.0.0"
+version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "41ed9a86bf92ae6580e0a31281f65a1b1d867c0cc68d5346e2ae128dddfa6a7d"
+checksum = "3a30da5c5f2d5e72842e00bcb57657162cdabef0931f40e2deb9b4140440cecd"
 
 [[package]]
 name = "anstyle-parse"
-version = "0.2.0"
+version = "0.2.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e765fd216e48e067936442276d1d57399e37bce53c264d6fefbe298080cb57ee"
+checksum = "938874ff5980b03a87c5524b3ae5b59cf99b1d6bc836848df7bc5ada9643c333"
 dependencies = [
  "utf8parse",
 ]
@@ -355,7 +355,7 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
 dependencies = [
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -365,7 +365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "180abfa45703aebe0093f79badacc01b8fd4ea2e35118747e5811127f926e188"
 dependencies = [
  "anstyle",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -762,9 +762,9 @@ dependencies = [
 
 [[package]]
 name = "clap"
-version = "4.3.1"
+version = "4.3.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b4ed2379f8603fa2b7509891660e802b88c70a79a6427a70abb5968054de2c28"
+checksum = "6320c6d1c98b6981da7bb2dcecbd0be9dc98d42165fa8326b21000f7dbfde6d0"
 dependencies = [
  "clap_builder",
  "clap_derive",
@@ -773,9 +773,9 @@ dependencies = [
 
 [[package]]
 name = "clap_builder"
-version = "4.3.1"
+version = "4.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72394f3339a76daf211e57d4bcb374410f3965dcc606dd0e03738c7888766980"
+checksum = "2e53afce1efce6ed1f633cf0e57612fe51db54a1ee4fd8f8503d078fe02d69ae"
 dependencies = [
  "anstream",
  "anstyle",
@@ -786,9 +786,9 @@ dependencies = [
 
 [[package]]
 name = "clap_derive"
-version = "4.3.1"
+version = "4.3.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59e9ef9a08ee1c0e1f2e162121665ac45ac3783b0f897db7244ae75ad9a8f65b"
+checksum = "b8cd2b2a819ad6eec39e8f1d6b53001af1e5469f8c177579cdaeb313115b825f"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -877,9 +877,9 @@ checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e"
 
 [[package]]
 name = "cpufeatures"
-version = "0.2.7"
+version = "0.2.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58"
+checksum = "03e69e28e9f7f77debdedbaafa2866e1de9ba56df55a8bd7cfc724c25a09987c"
 dependencies = [
  "libc",
 ]
@@ -905,9 +905,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-epoch"
-version = "0.9.14"
+version = "0.9.15"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695"
+checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7"
 dependencies = [
  "autocfg",
  "cfg-if",
@@ -918,9 +918,9 @@ dependencies = [
 
 [[package]]
 name = "crossbeam-utils"
-version = "0.8.15"
+version = "0.8.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b"
+checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
 dependencies = [
  "cfg-if",
 ]
@@ -991,7 +991,7 @@ dependencies = [
  "hashbrown 0.12.3",
  "lock_api",
  "once_cell",
- "parking_lot_core 0.9.7",
+ "parking_lot_core 0.9.8",
 ]
 
 [[package]]
@@ -1089,7 +1089,7 @@ checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a"
 dependencies = [
  "errno-dragonfly",
  "libc",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -1135,9 +1135,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
 
 [[package]]
 name = "form_urlencoded"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8"
+checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652"
 dependencies = [
  "percent-encoding",
 ]
@@ -1272,9 +1272,9 @@ dependencies = [
 
 [[package]]
 name = "getrandom"
-version = "0.2.9"
+version = "0.2.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
 dependencies = [
  "cfg-if",
  "libc",
@@ -1468,9 +1468,9 @@ checksum = "0646026eb1b3eea4cd9ba47912ea5ce9cc07713d105b1a14698f4e6433d348b7"
 dependencies = [
  "http",
  "hyper",
- "rustls 0.21.1",
+ "rustls 0.21.2",
  "tokio",
- "tokio-rustls 0.24.0",
+ "tokio-rustls 0.24.1",
 ]
 
 [[package]]
@@ -1493,9 +1493,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
 
 [[package]]
 name = "idna"
-version = "0.3.0"
+version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6"
+checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c"
 dependencies = [
  "unicode-bidi",
  "unicode-normalization",
@@ -1537,7 +1537,7 @@ checksum = "eae7b9aee968036d54dce06cebaefd919e4472e753296daccd6d344e3e2df0c2"
 dependencies = [
  "hermit-abi 0.3.1",
  "libc",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -1565,7 +1565,7 @@ dependencies = [
  "hermit-abi 0.3.1",
  "io-lifetimes",
  "rustix",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -1594,9 +1594,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
 
 [[package]]
 name = "js-sys"
-version = "0.3.63"
+version = "0.3.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f37a4a5928311ac501dee68b3c7613a1037d0edb30c8e5427bd832d55d1b790"
+checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
 dependencies = [
  "wasm-bindgen",
 ]
@@ -1629,9 +1629,9 @@ dependencies = [
 
 [[package]]
 name = "libc"
-version = "0.2.144"
+version = "0.2.146"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1"
+checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b"
 
 [[package]]
 name = "libm"
@@ -1671,9 +1671,9 @@ checksum = "e34f76eb3611940e0e7d53a9aaa4e6a3151f69541a282fd0dad5571420c53ff1"
 
 [[package]]
 name = "lock_api"
-version = "0.4.9"
+version = "0.4.10"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df"
+checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -1681,9 +1681,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.18"
+version = "0.4.19"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de"
+checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
 
 [[package]]
 name = "lru"
@@ -1758,9 +1758,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
 
 [[package]]
 name = "memoffset"
-version = "0.8.0"
+version = "0.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1"
+checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c"
 dependencies = [
  "autocfg",
 ]
@@ -1887,7 +1887,7 @@ dependencies = [
  "libc",
  "log",
  "wasi",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -2015,9 +2015,9 @@ dependencies = [
 
 [[package]]
 name = "once_cell"
-version = "1.17.2"
+version = "1.18.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b"
+checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
 
 [[package]]
 name = "opentelemetry"
@@ -2141,7 +2141,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
 dependencies = [
  "lock_api",
- "parking_lot_core 0.9.7",
+ "parking_lot_core 0.9.8",
 ]
 
 [[package]]
@@ -2153,22 +2153,22 @@ dependencies = [
  "cfg-if",
  "instant",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.2.16",
  "smallvec",
  "winapi",
 ]
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.7"
+version = "0.9.8"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521"
+checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
 dependencies = [
  "cfg-if",
  "libc",
- "redox_syscall",
+ "redox_syscall 0.3.5",
  "smallvec",
- "windows-sys 0.45.0",
+ "windows-targets",
 ]
 
 [[package]]
@@ -2205,15 +2205,15 @@ dependencies = [
 
 [[package]]
 name = "percent-encoding"
-version = "2.2.0"
+version = "2.3.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e"
+checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94"
 
 [[package]]
 name = "pest"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e68e84bfb01f0507134eac1e9b410a12ba379d064eab48c50ba4ce329a527b70"
+checksum = "f73935e4d55e2abf7f130186537b19e7a4abc886a0252380b59248af473a3fc9"
 dependencies = [
  "thiserror",
  "ucd-trie",
@@ -2221,9 +2221,9 @@ dependencies = [
 
 [[package]]
 name = "pest_derive"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6b79d4c71c865a25a4322296122e3924d30bc8ee0834c8bfc8b95f7f054afbfb"
+checksum = "aef623c9bbfa0eedf5a0efba11a5ee83209c326653ca31ff019bec3a95bfff2b"
 dependencies = [
  "pest",
  "pest_generator",
@@ -2231,9 +2231,9 @@ dependencies = [
 
 [[package]]
 name = "pest_generator"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6c435bf1076437b851ebc8edc3a18442796b30f1728ffea6262d59bbe28b077e"
+checksum = "b3e8cba4ec22bada7fc55ffe51e2deb6a0e0db2d0b7ab0b103acc80d2510c190"
 dependencies = [
  "pest",
  "pest_meta",
@@ -2244,9 +2244,9 @@ dependencies = [
 
 [[package]]
 name = "pest_meta"
-version = "2.6.0"
+version = "2.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "745a452f8eb71e39ffd8ee32b3c5f51d03845f99786fa9b68db6ff509c505411"
+checksum = "a01f71cb40bd8bb94232df14b946909e14660e33fc05db3e50ae2a82d7ea0ca0"
 dependencies = [
  "once_cell",
  "pest",
@@ -2388,9 +2388,9 @@ dependencies = [
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.59"
+version = "1.0.60"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6aeca18b86b413c660b781aa319e4e2648a3e6f9eadc9b47e9038e6fe9f3451b"
+checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
 dependencies = [
  "unicode-ident",
 ]
@@ -2520,12 +2520,21 @@ dependencies = [
 ]
 
 [[package]]
-name = "regex"
-version = "1.8.3"
+name = "redox_syscall"
+version = "0.3.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "81ca098a9821bd52d6b24fd8b10bd081f47d39c22778cafaa75a2857a62c6390"
+checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
 dependencies = [
- "aho-corasick 1.0.1",
+ "bitflags",
+]
+
+[[package]]
+name = "regex"
+version = "1.8.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+dependencies = [
+ "aho-corasick 1.0.2",
  "memchr",
  "regex-syntax 0.7.2",
 ]
@@ -2575,13 +2584,13 @@ dependencies = [
  "once_cell",
  "percent-encoding",
  "pin-project-lite",
- "rustls 0.21.1",
+ "rustls 0.21.2",
  "rustls-pemfile",
  "serde",
  "serde_json",
  "serde_urlencoded",
  "tokio",
- "tokio-rustls 0.24.0",
+ "tokio-rustls 0.24.1",
  "tokio-util",
  "tower-service",
  "url",
@@ -2713,16 +2722,16 @@ dependencies = [
 
 [[package]]
 name = "rustix"
-version = "0.37.19"
+version = "0.37.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acf8729d8542766f1b2cf77eb034d52f40d375bb8b615d0b147089946e16613d"
+checksum = "b96e891d04aa506a6d1f318d2771bcb1c7dfda84e126660ace067c9b474bb2c0"
 dependencies = [
  "bitflags",
  "errno",
  "io-lifetimes",
  "libc",
  "linux-raw-sys",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -2739,9 +2748,9 @@ dependencies = [
 
 [[package]]
 name = "rustls"
-version = "0.21.1"
+version = "0.21.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c911ba11bc8433e811ce56fde130ccf32f5127cab0e0194e9c68c5a5b671791e"
+checksum = "e32ca28af694bc1bbf399c33a516dbdf1c90090b8ab23c2bc24f834aa2247f5f"
 dependencies = [
  "log",
  "ring",
@@ -2804,18 +2813,18 @@ checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed"
 
 [[package]]
 name = "serde"
-version = "1.0.163"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2113ab51b87a539ae008b5c6c02dc020ffa39afd2d83cffcb3f4eb2722cebec2"
+checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.163"
+version = "1.0.164"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8c805777e3930c8883389c602315a24224bcc738b63905ef87cd1420353ea93e"
+checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -2824,9 +2833,9 @@ dependencies = [
 
 [[package]]
 name = "serde_json"
-version = "1.0.96"
+version = "1.0.97"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1"
+checksum = "bdf3bf93142acad5821c99197022e170842cdbc1c30482b98750c688c640842a"
 dependencies = [
  "itoa",
  "ryu",
@@ -2879,9 +2888,9 @@ dependencies = [
 
 [[package]]
 name = "sha2"
-version = "0.10.6"
+version = "0.10.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0"
+checksum = "479fb9d862239e610720565ca91403019f2f00410f1864c5aa7479b950a76ed8"
 dependencies = [
  "cfg-if",
  "cpufeatures",
@@ -3175,9 +3184,9 @@ dependencies = [
 
 [[package]]
 name = "time"
-version = "0.3.21"
+version = "0.3.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3403384eaacbca9923fa06940178ac13e4edb725486d70e8e15881d0c836cc"
+checksum = "ea9e1b3cf1243ae005d9e74085d4d542f3125458f3a81af210d901dcd7411efd"
 dependencies = [
  "itoa",
  "serde",
@@ -3231,7 +3240,7 @@ dependencies = [
  "socket2",
  "tokio-macros",
  "tracing",
- "windows-sys 0.48.0",
+ "windows-sys",
 ]
 
 [[package]]
@@ -3268,11 +3277,11 @@ dependencies = [
 
 [[package]]
 name = "tokio-rustls"
-version = "0.24.0"
+version = "0.24.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e0d409377ff5b1e3ca6437aa86c1eb7d40c134bfec254e44c830defa92669db5"
+checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081"
 dependencies = [
- "rustls 0.21.1",
+ "rustls 0.21.2",
  "tokio",
 ]
 
@@ -3463,9 +3472,9 @@ dependencies = [
 
 [[package]]
 name = "tracing-attributes"
-version = "0.1.24"
+version = "0.1.26"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f57e3ca2a01450b1a921183a9c9cbfda207fd822cef4ccb00a65402cbba7a74"
+checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3616,9 +3625,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
 
 [[package]]
 name = "url"
-version = "2.3.1"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643"
+checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb"
 dependencies = [
  "form_urlencoded",
  "idna",
@@ -3646,9 +3655,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
 
 [[package]]
 name = "uuid"
-version = "1.3.3"
+version = "1.3.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "345444e32442451b267fc254ae85a209c64be56d2890e601a0c37ff0c3c5ecd2"
+checksum = "0fa2982af2eec27de306107c027578ff7f423d65f7250e40ce0fea8f45248b81"
 dependencies = [
  "getrandom",
  "serde",
@@ -3668,11 +3677,10 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "want"
-version = "0.3.0"
+version = "0.3.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0"
+checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
 dependencies = [
- "log",
  "try-lock",
 ]
 
@@ -3684,9 +3692,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
 name = "wasm-bindgen"
-version = "0.2.86"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5bba0e8cb82ba49ff4e229459ff22a191bbe9a1cb3a341610c9c33efc27ddf73"
+checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
 dependencies = [
  "cfg-if",
  "wasm-bindgen-macro",
@@ -3694,9 +3702,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-backend"
-version = "0.2.86"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "19b04bc93f9d6bdee709f6bd2118f57dd6679cf1176a1af464fca3ab0d66d8fb"
+checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
 dependencies = [
  "bumpalo",
  "log",
@@ -3709,9 +3717,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-futures"
-version = "0.4.36"
+version = "0.4.37"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2d1985d03709c53167ce907ff394f5316aa22cb4e12761295c5dc57dacb6297e"
+checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03"
 dependencies = [
  "cfg-if",
  "js-sys",
@@ -3721,9 +3729,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro"
-version = "0.2.86"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "14d6b024f1a526bb0234f52840389927257beb670610081360e5a03c5df9c258"
+checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
 dependencies = [
  "quote",
  "wasm-bindgen-macro-support",
@@ -3731,9 +3739,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-macro-support"
-version = "0.2.86"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e128beba882dd1eb6200e1dc92ae6c5dbaa4311aa7bb211ca035779e5efc39f8"
+checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -3744,9 +3752,9 @@ dependencies = [
 
 [[package]]
 name = "wasm-bindgen-shared"
-version = "0.2.86"
+version = "0.2.87"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed9d5b4305409d1fc9482fee2d7f9bcbf24b3972bf59817ef757e23982242a93"
+checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
 
 [[package]]
 name = "wasm-streams"
@@ -3763,9 +3771,9 @@ dependencies = [
 
 [[package]]
 name = "web-sys"
-version = "0.3.63"
+version = "0.3.64"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3bdd9ef4e984da1187bf8110c5cf5b845fbc87a23602cdf912386a76fcd3a7c2"
+checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b"
 dependencies = [
  "js-sys",
  "wasm-bindgen",
@@ -3812,37 +3820,13 @@ version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
 
-[[package]]
-name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets 0.42.2",
-]
-
 [[package]]
 name = "windows-sys"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows-targets 0.48.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
+ "windows-targets",
 ]
 
 [[package]]
@@ -3851,93 +3835,51 @@ version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5"
 dependencies = [
- "windows_aarch64_gnullvm 0.48.0",
- "windows_aarch64_msvc 0.48.0",
- "windows_i686_gnu 0.48.0",
- "windows_i686_msvc 0.48.0",
- "windows_x86_64_gnu 0.48.0",
- "windows_x86_64_gnullvm 0.48.0",
- "windows_x86_64_msvc 0.48.0",
+ "windows_aarch64_gnullvm",
+ "windows_aarch64_msvc",
+ "windows_i686_gnu",
+ "windows_i686_msvc",
+ "windows_x86_64_gnu",
+ "windows_x86_64_gnullvm",
+ "windows_x86_64_msvc",
 ]
 
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
-
 [[package]]
 name = "windows_aarch64_gnullvm"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc"
 
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
 [[package]]
 name = "windows_aarch64_msvc"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3"
 
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
-
 [[package]]
 name = "windows_i686_gnu"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241"
 
-[[package]]
-name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
-
 [[package]]
 name = "windows_i686_msvc"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00"
 
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
-
 [[package]]
 name = "windows_x86_64_gnu"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1"
 
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
-
 [[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953"
 
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
-
 [[package]]
 name = "windows_x86_64_msvc"
 version = "0.48.0"
@@ -3946,9 +3888,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
 
 [[package]]
 name = "winnow"
-version = "0.4.6"
+version = "0.4.7"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "61de7bac303dc551fe038e2b3cef0f571087a47571ea6e79a87692ac99b99699"
+checksum = "ca0ace3845f0d96209f0375e6d367e3eb87eb65d27d445bdc9f1843a26f39448"
 dependencies = [
  "memchr",
 ]

From 8d565a1fbea7226c77d854dae7c882236585e2be Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 13:46:13 -0500
Subject: [PATCH 81/87] Add ability to tweak client pool size

---
 README.md         |  6 ++++++
 src/config.rs     |  9 +++++++++
 src/data/state.rs |  1 +
 src/main.rs       |  2 +-
 src/requests.rs   | 15 +++++++++++----
 5 files changed, 28 insertions(+), 5 deletions(-)

diff --git a/README.md b/README.md
index f177075..c369462 100644
--- a/README.md
+++ b/README.md
@@ -105,6 +105,7 @@ LOCAL_DOMAINS=masto.asonix.dog
 LOCAL_BLURB="<p>Welcome to my cool relay where I have cool relay things happening. I hope you enjoy your stay!</p>"
 PROMETHEUS_ADDR=0.0.0.0
 PROMETHEUS_PORT=9000
+CLIENT_POOL_SIZE=20
 ```
 
 #### Descriptions
@@ -154,6 +155,11 @@ Optional - description for the relay
 Optional - Address to bind to for serving the prometheus scrape endpoint
 ##### `PROMETHEUS_PORT`
 Optional - Port to bind to for serving the prometheus scrape endpoint
+##### `CLIENT_POOL_SIZE`
+Optional - How many connections the relay should maintain per thread. This value will be multiplied
+by two times the number of cores available to the relay. This defaults to 20, so a 4-core machine
+will have a maximum of 160 simultaneous outbound connections. If you run into problems related to
+"Too many open files", you can either decrease this number or increase the ulimit for your system.
 
 ### Subscribing
 Mastodon admins can subscribe to this relay by adding the `/inbox` route to their relay settings.
diff --git a/src/config.rs b/src/config.rs
index db21f9d..bf58533 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -45,6 +45,7 @@ pub(crate) struct ParsedConfig {
     local_blurb: Option<String>,
     prometheus_addr: Option<IpAddr>,
     prometheus_port: Option<u16>,
+    client_pool_size: usize,
 }
 
 #[derive(Clone)]
@@ -68,6 +69,7 @@ pub struct Config {
     local_domains: Vec<String>,
     local_blurb: Option<String>,
     prometheus_config: Option<PrometheusConfig>,
+    client_pool_size: usize,
 }
 
 #[derive(Clone)]
@@ -135,6 +137,7 @@ impl std::fmt::Debug for Config {
             .field("local_domains", &self.local_domains)
             .field("local_blurb", &self.local_blurb)
             .field("prometheus_config", &self.prometheus_config)
+            .field("client_pool_size", &self.client_pool_size)
             .finish()
     }
 }
@@ -164,6 +167,7 @@ impl Config {
             .set_default("local_blurb", None as Option<&str>)?
             .set_default("prometheus_addr", None as Option<&str>)?
             .set_default("prometheus_port", None as Option<u16>)?
+            .set_default("client_pool_size", 20u64)?
             .add_source(Environment::default())
             .build()?;
 
@@ -235,6 +239,7 @@ impl Config {
             local_domains,
             local_blurb: config.local_blurb,
             prometheus_config,
+            client_pool_size: config.client_pool_size,
         })
     }
 
@@ -414,6 +419,10 @@ impl Config {
         )
     }
 
+    pub(crate) fn client_pool_size(&self) -> usize {
+        self.client_pool_size
+    }
+
     pub(crate) fn source_code(&self) -> &IriString {
         &self.source_repo
     }
diff --git a/src/data/state.rs b/src/data/state.rs
index 4387974..d6c484b 100644
--- a/src/data/state.rs
+++ b/src/data/state.rs
@@ -47,6 +47,7 @@ impl State {
             config.user_agent(),
             self.breakers.clone(),
             self.last_online.clone(),
+            config.client_pool_size(),
         )
     }
 
diff --git a/src/main.rs b/src/main.rs
index 5f733d7..10f764c 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -148,7 +148,7 @@ fn client_main(config: Config, args: Args) -> JoinHandle<Result<(), anyhow::Erro
 }
 
 async fn do_client_main(config: Config, args: Args) -> Result<(), anyhow::Error> {
-    let client = requests::build_client(&config.user_agent());
+    let client = requests::build_client(&config.user_agent(), config.client_pool_size());
 
     if !args.blocks().is_empty() || !args.allowed().is_empty() {
         if args.undo() {
diff --git a/src/requests.rs b/src/requests.rs
index 0a2238e..efd3a99 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -4,7 +4,7 @@ use crate::{
 };
 use activitystreams::iri_string::types::IriString;
 use actix_web::http::header::Date;
-use awc::{error::SendRequestError, Client, ClientResponse};
+use awc::{error::SendRequestError, Client, ClientResponse, Connector};
 use base64::{engine::general_purpose::STANDARD, Engine};
 use dashmap::DashMap;
 use http_signature_normalization_actix::prelude::*;
@@ -145,6 +145,7 @@ impl Default for Breaker {
 
 #[derive(Clone)]
 pub(crate) struct Requests {
+    pool_size: usize,
     client: Rc<RefCell<Client>>,
     consecutive_errors: Rc<AtomicUsize>,
     error_limit: usize,
@@ -159,6 +160,7 @@ pub(crate) struct Requests {
 impl std::fmt::Debug for Requests {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("Requests")
+            .field("pool_size", &self.pool_size)
             .field("error_limit", &self.error_limit)
             .field("key_id", &self.key_id)
             .field("user_agent", &self.user_agent)
@@ -168,8 +170,11 @@ impl std::fmt::Debug for Requests {
     }
 }
 
-pub(crate) fn build_client(user_agent: &str) -> Client {
+pub(crate) fn build_client(user_agent: &str, pool_size: usize) -> Client {
+    let connector = Connector::new().limit(pool_size);
+
     Client::builder()
+        .connector(connector)
         .wrap(Tracing)
         .add_default_header(("User-Agent", user_agent.to_string()))
         .timeout(Duration::from_secs(15))
@@ -183,9 +188,11 @@ impl Requests {
         user_agent: String,
         breakers: Breakers,
         last_online: Arc<LastOnline>,
+        pool_size: usize,
     ) -> Self {
         Requests {
-            client: Rc::new(RefCell::new(build_client(&user_agent))),
+            pool_size,
+            client: Rc::new(RefCell::new(build_client(&user_agent, pool_size))),
             consecutive_errors: Rc::new(AtomicUsize::new(0)),
             error_limit: 3,
             key_id,
@@ -205,7 +212,7 @@ impl Requests {
         let count = self.consecutive_errors.fetch_add(1, Ordering::Relaxed);
         if count + 1 >= self.error_limit {
             tracing::warn!("{} consecutive errors, rebuilding http client", count + 1);
-            *self.client.borrow_mut() = build_client(&self.user_agent);
+            *self.client.borrow_mut() = build_client(&self.user_agent, self.pool_size);
             self.reset_err();
         }
     }

From 246e79b2618f1fd382d543e3c50d9f828e96f50f Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 13:47:40 -0500
Subject: [PATCH 82/87] Bump version

---
 Cargo.lock                     | 2 +-
 Cargo.toml                     | 2 +-
 README.md                      | 2 +-
 docker/prod/docker-compose.yml | 2 +-
 relay.nix                      | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 9db86e3..0259881 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -376,7 +376,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.82"
+version = "0.3.83"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 2609f47..9888d5b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.82"
+version = "0.3.83"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"
diff --git a/README.md b/README.md
index c369462..e4c6f9d 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ $ sudo docker run --rm -it \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \
-    asonix/relay:0.3.78
+    asonix/relay:0.3.83
 ```
 This will launch the relay with the database stored in "./sled/db-0.34" and listening on port 8080
 #### Cargo
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 7fe2704..5eeeeac 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.3'
 
 services:
   relay:
-    image: asonix/relay:v0.3.73
+    image: asonix/relay:v0.3.83
     ports:
       - "8079:8079"
     restart: always
diff --git a/relay.nix b/relay.nix
index 03db9d5..d132390 100644
--- a/relay.nix
+++ b/relay.nix
@@ -8,7 +8,7 @@
 
 rustPlatform.buildRustPackage {
   pname = "relay";
-  version = "0.3.82";
+  version = "0.3.83";
   src = ./.;
   cargoLock.lockFile = ./Cargo.lock;
 

From d40db33eb51ba69df3a6824fe37afd927fffcc9c Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 14:27:20 -0500
Subject: [PATCH 83/87] Don't drop and rebuild clients, share clients better

---
 src/main.rs     |  6 ++++--
 src/requests.rs | 40 +++++++---------------------------------
 2 files changed, 11 insertions(+), 35 deletions(-)

diff --git a/src/main.rs b/src/main.rs
index 10f764c..64945ae 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -259,10 +259,12 @@ async fn do_server_main(
 
     let bind_address = config.bind_address();
     let server = HttpServer::new(move || {
+        let requests = state.requests(&config);
+
         let app = App::new()
             .app_data(web::Data::new(db.clone()))
             .app_data(web::Data::new(state.clone()))
-            .app_data(web::Data::new(state.requests(&config)))
+            .app_data(web::Data::new(requests.clone()))
             .app_data(web::Data::new(actors.clone()))
             .app_data(web::Data::new(config.clone()))
             .app_data(web::Data::new(job_server.clone()))
@@ -285,7 +287,7 @@ async fn do_server_main(
                 web::resource("/inbox")
                     .wrap(config.digest_middleware())
                     .wrap(VerifySignature::new(
-                        MyVerify(state.requests(&config), actors.clone(), state.clone()),
+                        MyVerify(requests, actors.clone(), state.clone()),
                         Default::default(),
                     ))
                     .wrap(DebugPayload(config.debug()))
diff --git a/src/requests.rs b/src/requests.rs
index efd3a99..b71e6d1 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -16,12 +16,7 @@ use rsa::{
     RsaPrivateKey,
 };
 use std::{
-    cell::RefCell,
-    rc::Rc,
-    sync::{
-        atomic::{AtomicUsize, Ordering},
-        Arc,
-    },
+    sync::Arc,
     time::{Duration, SystemTime},
 };
 use tracing_awc::Tracing;
@@ -146,9 +141,7 @@ impl Default for Breaker {
 #[derive(Clone)]
 pub(crate) struct Requests {
     pool_size: usize,
-    client: Rc<RefCell<Client>>,
-    consecutive_errors: Rc<AtomicUsize>,
-    error_limit: usize,
+    client: Client,
     key_id: String,
     user_agent: String,
     private_key: RsaPrivateKey,
@@ -161,7 +154,6 @@ impl std::fmt::Debug for Requests {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         f.debug_struct("Requests")
             .field("pool_size", &self.pool_size)
-            .field("error_limit", &self.error_limit)
             .field("key_id", &self.key_id)
             .field("user_agent", &self.user_agent)
             .field("config", &self.config)
@@ -192,9 +184,7 @@ impl Requests {
     ) -> Self {
         Requests {
             pool_size,
-            client: Rc::new(RefCell::new(build_client(&user_agent, pool_size))),
-            consecutive_errors: Rc::new(AtomicUsize::new(0)),
-            error_limit: 3,
+            client: build_client(&user_agent, pool_size),
             key_id,
             user_agent,
             private_key,
@@ -208,34 +198,18 @@ impl Requests {
         self.breakers.succeed(iri);
     }
 
-    fn count_err(&self) {
-        let count = self.consecutive_errors.fetch_add(1, Ordering::Relaxed);
-        if count + 1 >= self.error_limit {
-            tracing::warn!("{} consecutive errors, rebuilding http client", count + 1);
-            *self.client.borrow_mut() = build_client(&self.user_agent, self.pool_size);
-            self.reset_err();
-        }
-    }
-
-    fn reset_err(&self) {
-        self.consecutive_errors.swap(0, Ordering::Relaxed);
-    }
-
     async fn check_response(
         &self,
         parsed_url: &IriString,
         res: Result<ClientResponse, SendRequestError>,
     ) -> Result<ClientResponse, Error> {
         if res.is_err() {
-            self.count_err();
             self.breakers.fail(&parsed_url);
         }
 
         let mut res =
             res.map_err(|e| ErrorKind::SendRequest(parsed_url.to_string(), e.to_string()))?;
 
-        self.reset_err();
-
         if res.status().is_server_error() {
             self.breakers.fail(&parsed_url);
 
@@ -325,8 +299,8 @@ impl Requests {
         let signer = self.signer();
         let span = tracing::Span::current();
 
-        let client: Client = self.client.borrow().clone();
-        let res = client
+        let res = self
+            .client
             .get(url.as_str())
             .insert_header(("Accept", accept))
             .insert_header(Date(SystemTime::now().into()))
@@ -385,8 +359,8 @@ impl Requests {
         let span = tracing::Span::current();
         let item_string = serde_json::to_string(item)?;
 
-        let client: Client = self.client.borrow().clone();
-        let (req, body) = client
+        let (req, body) = self
+            .client
             .post(inbox.as_str())
             .insert_header(("Accept", accept))
             .insert_header(("Content-Type", content_type))

From e005adfcf8baef6ec0b5fa2ea7d3887c523f4896 Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 14:32:14 -0500
Subject: [PATCH 84/87] Bump version

---
 Cargo.lock                     | 2 +-
 Cargo.toml                     | 2 +-
 README.md                      | 2 +-
 docker/prod/docker-compose.yml | 2 +-
 relay.nix                      | 4 +---
 5 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index 0259881..b5ae683 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -376,7 +376,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.83"
+version = "0.3.84"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 9888d5b..5ae7ce7 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.83"
+version = "0.3.84"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"
diff --git a/README.md b/README.md
index e4c6f9d..ad86105 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ $ sudo docker run --rm -it \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \
-    asonix/relay:0.3.83
+    asonix/relay:0.3.84
 ```
 This will launch the relay with the database stored in "./sled/db-0.34" and listening on port 8080
 #### Cargo
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 5eeeeac..52f3b2a 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.3'
 
 services:
   relay:
-    image: asonix/relay:v0.3.83
+    image: asonix/relay:0.3.84
     ports:
       - "8079:8079"
     restart: always
diff --git a/relay.nix b/relay.nix
index d132390..ef64492 100644
--- a/relay.nix
+++ b/relay.nix
@@ -1,14 +1,12 @@
 { lib
-, makeWrapper
 , nixosTests
 , protobuf
 , rustPlatform
-, stdenv
 }:
 
 rustPlatform.buildRustPackage {
   pname = "relay";
-  version = "0.3.83";
+  version = "0.3.84";
   src = ./.;
   cargoLock.lockFile = ./Cargo.lock;
 

From 74f35faa224a06d684f6fbaf97553c3e1dd70eab Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 15:01:56 -0500
Subject: [PATCH 85/87] Keep client in thread-local storage

---
 src/requests.rs | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/src/requests.rs b/src/requests.rs
index b71e6d1..a1fc8ef 100644
--- a/src/requests.rs
+++ b/src/requests.rs
@@ -162,15 +162,25 @@ impl std::fmt::Debug for Requests {
     }
 }
 
-pub(crate) fn build_client(user_agent: &str, pool_size: usize) -> Client {
-    let connector = Connector::new().limit(pool_size);
+thread_local! {
+    static CLIENT: std::cell::OnceCell<Client> = std::cell::OnceCell::new();
+}
 
-    Client::builder()
-        .connector(connector)
-        .wrap(Tracing)
-        .add_default_header(("User-Agent", user_agent.to_string()))
-        .timeout(Duration::from_secs(15))
-        .finish()
+pub(crate) fn build_client(user_agent: &str, pool_size: usize) -> Client {
+    CLIENT.with(|client| {
+        client
+            .get_or_init(|| {
+                let connector = Connector::new().limit(pool_size);
+
+                Client::builder()
+                    .connector(connector)
+                    .wrap(Tracing)
+                    .add_default_header(("User-Agent", user_agent.to_string()))
+                    .timeout(Duration::from_secs(15))
+                    .finish()
+            })
+            .clone()
+    })
 }
 
 impl Requests {

From 346664396c34f5bddce8bd6d8b3eebf2be5be2da Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 15:08:59 -0500
Subject: [PATCH 86/87] Run workers on handler threads

---
 src/jobs.rs | 21 ++++++++-------------
 src/main.rs | 13 ++++---------
 2 files changed, 12 insertions(+), 22 deletions(-)

diff --git a/src/jobs.rs b/src/jobs.rs
index 0bad1ac..e2b6aef 100644
--- a/src/jobs.rs
+++ b/src/jobs.rs
@@ -21,9 +21,9 @@ use crate::{
 };
 use background_jobs::{
     memory_storage::{ActixTimer, Storage},
-    Job, Manager, QueueHandle, WorkerConfig,
+    Job, QueueHandle, WorkerConfig,
 };
-use std::{convert::TryFrom, num::NonZeroUsize, time::Duration};
+use std::time::Duration;
 
 fn debug_object(activity: &serde_json::Value) -> &serde_json::Value {
     let mut object = &activity["object"]["type"];
@@ -44,11 +44,8 @@ pub(crate) fn create_workers(
     actors: ActorCache,
     media: MediaCache,
     config: Config,
-) -> (Manager, JobServer) {
-    let parallelism = std::thread::available_parallelism()
-        .unwrap_or_else(|_| NonZeroUsize::try_from(1).expect("nonzero"));
-
-    let shared = WorkerConfig::new_managed(Storage::new(ActixTimer), move |queue_handle| {
+) -> JobServer {
+    let queue_handle = WorkerConfig::new(Storage::new(ActixTimer), move |queue_handle| {
         JobState::new(
             state.clone(),
             actors.clone(),
@@ -72,14 +69,12 @@ pub(crate) fn create_workers(
     .set_worker_count("maintenance", 2)
     .set_worker_count("apub", 2)
     .set_worker_count("deliver", 8)
-    .start_with_threads(parallelism);
+    .start();
 
-    shared.every(Duration::from_secs(60 * 5), Listeners);
-    shared.every(Duration::from_secs(60 * 10), RecordLastOnline);
+    queue_handle.every(Duration::from_secs(60 * 5), Listeners);
+    queue_handle.every(Duration::from_secs(60 * 10), RecordLastOnline);
 
-    let job_server = JobServer::new(shared.queue_handle().clone());
-
-    (shared, job_server)
+    JobServer::new(queue_handle)
 }
 
 #[derive(Clone, Debug)]
diff --git a/src/main.rs b/src/main.rs
index 64945ae..6ce2f22 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -246,10 +246,6 @@ async fn do_server_main(
     tracing::warn!("Creating state");
     let state = State::build(db.clone()).await?;
 
-    tracing::warn!("Creating workers");
-    let (manager, job_server) =
-        create_workers(state.clone(), actors.clone(), media.clone(), config.clone());
-
     if let Some((token, admin_handle)) = config.telegram_info() {
         tracing::warn!("Creating telegram handler");
         telegram::start(admin_handle.to_owned(), db.clone(), token);
@@ -261,13 +257,16 @@ async fn do_server_main(
     let server = HttpServer::new(move || {
         let requests = state.requests(&config);
 
+        let job_server =
+            create_workers(state.clone(), actors.clone(), media.clone(), config.clone());
+
         let app = App::new()
             .app_data(web::Data::new(db.clone()))
             .app_data(web::Data::new(state.clone()))
             .app_data(web::Data::new(requests.clone()))
             .app_data(web::Data::new(actors.clone()))
             .app_data(web::Data::new(config.clone()))
-            .app_data(web::Data::new(job_server.clone()))
+            .app_data(web::Data::new(job_server))
             .app_data(web::Data::new(media.clone()))
             .app_data(web::Data::new(collector.clone()));
 
@@ -336,10 +335,6 @@ async fn do_server_main(
 
     tracing::warn!("Server closed");
 
-    drop(manager);
-
-    tracing::warn!("Main complete");
-
     Ok(())
 }
 

From 7a002295083ec227659d7756eb982f08b6d288ea Mon Sep 17 00:00:00 2001
From: asonix <asonix@asonix.dog>
Date: Fri, 23 Jun 2023 15:15:27 -0500
Subject: [PATCH 87/87] Bump version, update docs

---
 Cargo.lock                     | 2 +-
 Cargo.toml                     | 2 +-
 README.md                      | 8 ++++----
 docker/prod/docker-compose.yml | 2 +-
 relay.nix                      | 2 +-
 5 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b5ae683..0a02148 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -376,7 +376,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
 name = "ap-relay"
-version = "0.3.84"
+version = "0.3.85"
 dependencies = [
  "activitystreams",
  "activitystreams-ext",
diff --git a/Cargo.toml b/Cargo.toml
index 5ae7ce7..d6358f9 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "ap-relay"
 description = "A simple activitypub relay"
-version = "0.3.84"
+version = "0.3.85"
 authors = ["asonix <asonix@asonix.dog>"]
 license = "AGPL-3.0"
 readme = "README.md"
diff --git a/README.md b/README.md
index ad86105..66a6544 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@ $ sudo docker run --rm -it \
     -e ADDR=0.0.0.0 \
     -e SLED_PATH=/mnt/sled/db-0.34 \
     -p 8080:8080 \
-    asonix/relay:0.3.84
+    asonix/relay:0.3.85
 ```
 This will launch the relay with the database stored in "./sled/db-0.34" and listening on port 8080
 #### Cargo
@@ -157,9 +157,9 @@ Optional - Address to bind to for serving the prometheus scrape endpoint
 Optional - Port to bind to for serving the prometheus scrape endpoint
 ##### `CLIENT_POOL_SIZE`
 Optional - How many connections the relay should maintain per thread. This value will be multiplied
-by two times the number of cores available to the relay. This defaults to 20, so a 4-core machine
-will have a maximum of 160 simultaneous outbound connections. If you run into problems related to
-"Too many open files", you can either decrease this number or increase the ulimit for your system.
+by the number of cores available to the relay. This defaults to 20, so a 4-core machine will have a
+maximum of 160 simultaneous outbound connections. If you run into problems related to "Too many open
+files", you can either decrease this number or increase the ulimit for your system.
 
 ### Subscribing
 Mastodon admins can subscribe to this relay by adding the `/inbox` route to their relay settings.
diff --git a/docker/prod/docker-compose.yml b/docker/prod/docker-compose.yml
index 52f3b2a..54e2a11 100644
--- a/docker/prod/docker-compose.yml
+++ b/docker/prod/docker-compose.yml
@@ -2,7 +2,7 @@ version: '3.3'
 
 services:
   relay:
-    image: asonix/relay:0.3.84
+    image: asonix/relay:0.3.85
     ports:
       - "8079:8079"
     restart: always
diff --git a/relay.nix b/relay.nix
index ef64492..08d4a73 100644
--- a/relay.nix
+++ b/relay.nix
@@ -6,7 +6,7 @@
 
 rustPlatform.buildRustPackage {
   pname = "relay";
-  version = "0.3.84";
+  version = "0.3.85";
   src = ./.;
   cargoLock.lockFile = ./Cargo.lock;