+1355
-225
Cargo.lock
+1355
-225
Cargo.lock
···
24
24
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
25
25
dependencies = [
26
26
"cfg-if",
27
-
"getrandom 0.3.3",
28
27
"once_cell",
29
28
"version_check",
30
29
"zerocopy",
···
46
45
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
47
46
48
47
[[package]]
48
+
name = "android-tzdata"
49
+
version = "0.1.1"
50
+
source = "registry+https://github.com/rust-lang/crates.io-index"
51
+
checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
52
+
53
+
[[package]]
54
+
name = "android_system_properties"
55
+
version = "0.1.5"
56
+
source = "registry+https://github.com/rust-lang/crates.io-index"
57
+
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
58
+
dependencies = [
59
+
"libc",
60
+
]
61
+
62
+
[[package]]
63
+
name = "anyhow"
64
+
version = "1.0.99"
65
+
source = "registry+https://github.com/rust-lang/crates.io-index"
66
+
checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100"
67
+
68
+
[[package]]
69
+
name = "async-compression"
70
+
version = "0.4.27"
71
+
source = "registry+https://github.com/rust-lang/crates.io-index"
72
+
checksum = "ddb939d66e4ae03cee6091612804ba446b12878410cfa17f785f4dd67d4014e8"
73
+
dependencies = [
74
+
"futures-core",
75
+
"memchr",
76
+
"pin-project-lite",
77
+
"tokio",
78
+
"zstd",
79
+
"zstd-safe",
80
+
]
81
+
82
+
[[package]]
49
83
name = "async-trait"
50
84
version = "0.1.89"
51
85
source = "registry+https://github.com/rust-lang/crates.io-index"
···
53
87
dependencies = [
54
88
"proc-macro2",
55
89
"quote",
56
-
"syn 2.0.105",
90
+
"syn",
57
91
]
58
92
59
93
[[package]]
···
66
100
]
67
101
68
102
[[package]]
103
+
name = "atomic-waker"
104
+
version = "1.1.2"
105
+
source = "registry+https://github.com/rust-lang/crates.io-index"
106
+
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
107
+
108
+
[[package]]
69
109
name = "autocfg"
70
110
version = "1.5.0"
71
111
source = "registry+https://github.com/rust-lang/crates.io-index"
···
73
113
74
114
[[package]]
75
115
name = "axum"
76
-
version = "0.7.9"
116
+
version = "0.8.4"
77
117
source = "registry+https://github.com/rust-lang/crates.io-index"
78
-
checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f"
118
+
checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5"
79
119
dependencies = [
80
-
"async-trait",
81
120
"axum-core",
82
121
"axum-macros",
83
122
"bytes",
123
+
"form_urlencoded",
84
124
"futures-util",
85
125
"http",
86
126
"http-body",
···
108
148
109
149
[[package]]
110
150
name = "axum-core"
111
-
version = "0.4.5"
151
+
version = "0.5.2"
112
152
source = "registry+https://github.com/rust-lang/crates.io-index"
113
-
checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199"
153
+
checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
114
154
dependencies = [
115
-
"async-trait",
116
155
"bytes",
117
-
"futures-util",
156
+
"futures-core",
118
157
"http",
119
158
"http-body",
120
159
"http-body-util",
···
129
168
130
169
[[package]]
131
170
name = "axum-macros"
132
-
version = "0.4.2"
171
+
version = "0.5.0"
133
172
source = "registry+https://github.com/rust-lang/crates.io-index"
134
-
checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce"
173
+
checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c"
135
174
dependencies = [
136
175
"proc-macro2",
137
176
"quote",
138
-
"syn 2.0.105",
177
+
"syn",
178
+
]
179
+
180
+
[[package]]
181
+
name = "axum-template"
182
+
version = "3.0.0"
183
+
source = "registry+https://github.com/rust-lang/crates.io-index"
184
+
checksum = "3df50f7d669bfc3a8c348f08f536fe37e7acfbeded3cfdffd2ad3d76725fc40c"
185
+
dependencies = [
186
+
"axum",
187
+
"handlebars",
188
+
"serde",
189
+
"thiserror 2.0.14",
139
190
]
140
191
141
192
[[package]]
···
155
206
156
207
[[package]]
157
208
name = "base64"
158
-
version = "0.21.7"
209
+
version = "0.22.1"
159
210
source = "registry+https://github.com/rust-lang/crates.io-index"
160
-
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
211
+
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
161
212
162
213
[[package]]
163
214
name = "base64ct"
···
184
235
]
185
236
186
237
[[package]]
238
+
name = "bstr"
239
+
version = "1.12.0"
240
+
source = "registry+https://github.com/rust-lang/crates.io-index"
241
+
checksum = "234113d19d0d7d613b40e86fb654acf958910802bcceab913a4f9e7cda03b1a4"
242
+
dependencies = [
243
+
"memchr",
244
+
"serde",
245
+
]
246
+
247
+
[[package]]
248
+
name = "bumpalo"
249
+
version = "3.19.0"
250
+
source = "registry+https://github.com/rust-lang/crates.io-index"
251
+
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
252
+
253
+
[[package]]
187
254
name = "byteorder"
188
255
version = "1.5.0"
189
256
source = "registry+https://github.com/rust-lang/crates.io-index"
···
201
268
source = "registry+https://github.com/rust-lang/crates.io-index"
202
269
checksum = "2352e5597e9c544d5e6d9c95190d5d27738ade584fa8db0a16e130e5c2b5296e"
203
270
dependencies = [
271
+
"jobserver",
272
+
"libc",
204
273
"shlex",
205
274
]
206
275
···
211
280
checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268"
212
281
213
282
[[package]]
283
+
name = "chrono"
284
+
version = "0.4.41"
285
+
source = "registry+https://github.com/rust-lang/crates.io-index"
286
+
checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
287
+
dependencies = [
288
+
"android-tzdata",
289
+
"iana-time-zone",
290
+
"num-traits",
291
+
"windows-link",
292
+
]
293
+
294
+
[[package]]
295
+
name = "chumsky"
296
+
version = "0.9.3"
297
+
source = "registry+https://github.com/rust-lang/crates.io-index"
298
+
checksum = "8eebd66744a15ded14960ab4ccdbfb51ad3b81f51f3f04a80adac98c985396c9"
299
+
dependencies = [
300
+
"hashbrown 0.14.5",
301
+
"stacker",
302
+
]
303
+
304
+
[[package]]
305
+
name = "ciborium"
306
+
version = "0.2.2"
307
+
source = "registry+https://github.com/rust-lang/crates.io-index"
308
+
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
309
+
dependencies = [
310
+
"ciborium-io",
311
+
"ciborium-ll",
312
+
"serde",
313
+
]
314
+
315
+
[[package]]
316
+
name = "ciborium-io"
317
+
version = "0.2.2"
318
+
source = "registry+https://github.com/rust-lang/crates.io-index"
319
+
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
320
+
321
+
[[package]]
322
+
name = "ciborium-ll"
323
+
version = "0.2.2"
324
+
source = "registry+https://github.com/rust-lang/crates.io-index"
325
+
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
326
+
dependencies = [
327
+
"ciborium-io",
328
+
"half",
329
+
]
330
+
331
+
[[package]]
332
+
name = "cipher"
333
+
version = "0.4.4"
334
+
source = "registry+https://github.com/rust-lang/crates.io-index"
335
+
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
336
+
dependencies = [
337
+
"crypto-common",
338
+
"inout",
339
+
]
340
+
341
+
[[package]]
342
+
name = "concurrent-queue"
343
+
version = "2.5.0"
344
+
source = "registry+https://github.com/rust-lang/crates.io-index"
345
+
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
346
+
dependencies = [
347
+
"crossbeam-utils",
348
+
]
349
+
350
+
[[package]]
214
351
name = "const-oid"
215
352
version = "0.9.6"
216
353
source = "registry+https://github.com/rust-lang/crates.io-index"
217
354
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
218
355
219
356
[[package]]
357
+
name = "core-foundation"
358
+
version = "0.9.4"
359
+
source = "registry+https://github.com/rust-lang/crates.io-index"
360
+
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
361
+
dependencies = [
362
+
"core-foundation-sys",
363
+
"libc",
364
+
]
365
+
366
+
[[package]]
367
+
name = "core-foundation-sys"
368
+
version = "0.8.7"
369
+
source = "registry+https://github.com/rust-lang/crates.io-index"
370
+
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
371
+
372
+
[[package]]
220
373
name = "cpufeatures"
221
374
version = "0.2.17"
222
375
source = "registry+https://github.com/rust-lang/crates.io-index"
···
256
409
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
257
410
258
411
[[package]]
412
+
name = "crunchy"
413
+
version = "0.2.4"
414
+
source = "registry+https://github.com/rust-lang/crates.io-index"
415
+
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
416
+
417
+
[[package]]
259
418
name = "crypto-common"
260
419
version = "0.1.6"
261
420
source = "registry+https://github.com/rust-lang/crates.io-index"
···
266
425
]
267
426
268
427
[[package]]
428
+
name = "darling"
429
+
version = "0.20.11"
430
+
source = "registry+https://github.com/rust-lang/crates.io-index"
431
+
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
432
+
dependencies = [
433
+
"darling_core",
434
+
"darling_macro",
435
+
]
436
+
437
+
[[package]]
438
+
name = "darling_core"
439
+
version = "0.20.11"
440
+
source = "registry+https://github.com/rust-lang/crates.io-index"
441
+
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
442
+
dependencies = [
443
+
"fnv",
444
+
"ident_case",
445
+
"proc-macro2",
446
+
"quote",
447
+
"strsim",
448
+
"syn",
449
+
]
450
+
451
+
[[package]]
452
+
name = "darling_macro"
453
+
version = "0.20.11"
454
+
source = "registry+https://github.com/rust-lang/crates.io-index"
455
+
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
456
+
dependencies = [
457
+
"darling_core",
458
+
"quote",
459
+
"syn",
460
+
]
461
+
462
+
[[package]]
463
+
name = "dashmap"
464
+
version = "6.1.0"
465
+
source = "registry+https://github.com/rust-lang/crates.io-index"
466
+
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
467
+
dependencies = [
468
+
"cfg-if",
469
+
"crossbeam-utils",
470
+
"hashbrown 0.14.5",
471
+
"lock_api",
472
+
"once_cell",
473
+
"parking_lot_core",
474
+
]
475
+
476
+
[[package]]
269
477
name = "der"
270
478
version = "0.7.10"
271
479
source = "registry+https://github.com/rust-lang/crates.io-index"
···
277
485
]
278
486
279
487
[[package]]
488
+
name = "derive_builder"
489
+
version = "0.20.2"
490
+
source = "registry+https://github.com/rust-lang/crates.io-index"
491
+
checksum = "507dfb09ea8b7fa618fcf76e953f4f5e192547945816d5358edffe39f6f94947"
492
+
dependencies = [
493
+
"derive_builder_macro",
494
+
]
495
+
496
+
[[package]]
497
+
name = "derive_builder_core"
498
+
version = "0.20.2"
499
+
source = "registry+https://github.com/rust-lang/crates.io-index"
500
+
checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8"
501
+
dependencies = [
502
+
"darling",
503
+
"proc-macro2",
504
+
"quote",
505
+
"syn",
506
+
]
507
+
508
+
[[package]]
509
+
name = "derive_builder_macro"
510
+
version = "0.20.2"
511
+
source = "registry+https://github.com/rust-lang/crates.io-index"
512
+
checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c"
513
+
dependencies = [
514
+
"derive_builder_core",
515
+
"syn",
516
+
]
517
+
518
+
[[package]]
280
519
name = "digest"
281
520
version = "0.10.7"
282
521
source = "registry+https://github.com/rust-lang/crates.io-index"
···
296
535
dependencies = [
297
536
"proc-macro2",
298
537
"quote",
299
-
"syn 2.0.105",
538
+
"syn",
300
539
]
301
540
302
541
[[package]]
···
315
554
]
316
555
317
556
[[package]]
557
+
name = "email-encoding"
558
+
version = "0.4.1"
559
+
source = "registry+https://github.com/rust-lang/crates.io-index"
560
+
checksum = "9298e6504d9b9e780ed3f7dfd43a61be8cd0e09eb07f7706a945b0072b6670b6"
561
+
dependencies = [
562
+
"base64",
563
+
"memchr",
564
+
]
565
+
566
+
[[package]]
567
+
name = "email_address"
568
+
version = "0.2.9"
569
+
source = "registry+https://github.com/rust-lang/crates.io-index"
570
+
checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449"
571
+
572
+
[[package]]
318
573
name = "equivalent"
319
574
version = "1.0.2"
320
575
source = "registry+https://github.com/rust-lang/crates.io-index"
···
327
582
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
328
583
dependencies = [
329
584
"libc",
330
-
"windows-sys 0.60.2",
585
+
"windows-sys 0.59.0",
331
586
]
332
587
333
588
[[package]]
···
343
598
344
599
[[package]]
345
600
name = "event-listener"
346
-
version = "2.5.3"
601
+
version = "5.4.1"
347
602
source = "registry+https://github.com/rust-lang/crates.io-index"
348
-
checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0"
603
+
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
604
+
dependencies = [
605
+
"concurrent-queue",
606
+
"parking",
607
+
"pin-project-lite",
608
+
]
349
609
350
610
[[package]]
351
611
name = "fastrand"
···
371
631
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
372
632
373
633
[[package]]
634
+
name = "foldhash"
635
+
version = "0.1.5"
636
+
source = "registry+https://github.com/rust-lang/crates.io-index"
637
+
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
638
+
639
+
[[package]]
640
+
name = "foreign-types"
641
+
version = "0.3.2"
642
+
source = "registry+https://github.com/rust-lang/crates.io-index"
643
+
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
644
+
dependencies = [
645
+
"foreign-types-shared",
646
+
]
647
+
648
+
[[package]]
649
+
name = "foreign-types-shared"
650
+
version = "0.1.1"
651
+
source = "registry+https://github.com/rust-lang/crates.io-index"
652
+
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
653
+
654
+
[[package]]
374
655
name = "form_urlencoded"
375
656
version = "1.2.1"
376
657
source = "registry+https://github.com/rust-lang/crates.io-index"
···
380
661
]
381
662
382
663
[[package]]
664
+
name = "forwarded-header-value"
665
+
version = "0.1.1"
666
+
source = "registry+https://github.com/rust-lang/crates.io-index"
667
+
checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9"
668
+
dependencies = [
669
+
"nonempty",
670
+
"thiserror 1.0.69",
671
+
]
672
+
673
+
[[package]]
383
674
name = "futures-channel"
384
675
version = "0.3.31"
385
676
source = "registry+https://github.com/rust-lang/crates.io-index"
···
436
727
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
437
728
438
729
[[package]]
730
+
name = "futures-timer"
731
+
version = "3.0.3"
732
+
source = "registry+https://github.com/rust-lang/crates.io-index"
733
+
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
734
+
735
+
[[package]]
439
736
name = "futures-util"
440
737
version = "0.3.31"
441
738
source = "registry+https://github.com/rust-lang/crates.io-index"
···
479
776
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
480
777
dependencies = [
481
778
"cfg-if",
779
+
"js-sys",
482
780
"libc",
483
781
"r-efi",
484
782
"wasi 0.14.2+wasi-0.2.4",
783
+
"wasm-bindgen",
485
784
]
486
785
487
786
[[package]]
···
491
790
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
492
791
493
792
[[package]]
793
+
name = "globset"
794
+
version = "0.4.16"
795
+
source = "registry+https://github.com/rust-lang/crates.io-index"
796
+
checksum = "54a1028dfc5f5df5da8a56a73e6c153c9a9708ec57232470703592a3f18e49f5"
797
+
dependencies = [
798
+
"aho-corasick",
799
+
"bstr",
800
+
"log",
801
+
"regex-automata 0.4.9",
802
+
"regex-syntax 0.8.5",
803
+
]
804
+
805
+
[[package]]
806
+
name = "governor"
807
+
version = "0.10.1"
808
+
source = "registry+https://github.com/rust-lang/crates.io-index"
809
+
checksum = "444405bbb1a762387aa22dd569429533b54a1d8759d35d3b64cb39b0293eaa19"
810
+
dependencies = [
811
+
"cfg-if",
812
+
"dashmap",
813
+
"futures-sink",
814
+
"futures-timer",
815
+
"futures-util",
816
+
"getrandom 0.3.3",
817
+
"hashbrown 0.15.5",
818
+
"nonzero_ext",
819
+
"parking_lot",
820
+
"portable-atomic",
821
+
"quanta",
822
+
"rand 0.9.2",
823
+
"smallvec",
824
+
"spinning_top",
825
+
"web-time",
826
+
]
827
+
828
+
[[package]]
829
+
name = "h2"
830
+
version = "0.4.12"
831
+
source = "registry+https://github.com/rust-lang/crates.io-index"
832
+
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
833
+
dependencies = [
834
+
"atomic-waker",
835
+
"bytes",
836
+
"fnv",
837
+
"futures-core",
838
+
"futures-sink",
839
+
"http",
840
+
"indexmap",
841
+
"slab",
842
+
"tokio",
843
+
"tokio-util",
844
+
"tracing",
845
+
]
846
+
847
+
[[package]]
848
+
name = "half"
849
+
version = "2.6.0"
850
+
source = "registry+https://github.com/rust-lang/crates.io-index"
851
+
checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
852
+
dependencies = [
853
+
"cfg-if",
854
+
"crunchy",
855
+
]
856
+
857
+
[[package]]
858
+
name = "handlebars"
859
+
version = "6.3.2"
860
+
source = "registry+https://github.com/rust-lang/crates.io-index"
861
+
checksum = "759e2d5aea3287cb1190c8ec394f42866cb5bf74fcbf213f354e3c856ea26098"
862
+
dependencies = [
863
+
"derive_builder",
864
+
"log",
865
+
"num-order",
866
+
"pest",
867
+
"pest_derive",
868
+
"rust-embed",
869
+
"serde",
870
+
"serde_json",
871
+
"thiserror 2.0.14",
872
+
]
873
+
874
+
[[package]]
494
875
name = "hashbrown"
495
876
version = "0.14.5"
496
877
source = "registry+https://github.com/rust-lang/crates.io-index"
···
505
886
version = "0.15.5"
506
887
source = "registry+https://github.com/rust-lang/crates.io-index"
507
888
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
889
+
dependencies = [
890
+
"allocator-api2",
891
+
"equivalent",
892
+
"foldhash",
893
+
]
508
894
509
895
[[package]]
510
896
name = "hashlink"
511
-
version = "0.8.4"
897
+
version = "0.10.0"
512
898
source = "registry+https://github.com/rust-lang/crates.io-index"
513
-
checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7"
899
+
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
514
900
dependencies = [
515
-
"hashbrown 0.14.5",
901
+
"hashbrown 0.15.5",
516
902
]
517
903
518
904
[[package]]
519
905
name = "heck"
520
-
version = "0.4.1"
906
+
version = "0.5.0"
521
907
source = "registry+https://github.com/rust-lang/crates.io-index"
522
-
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
523
-
dependencies = [
524
-
"unicode-segmentation",
525
-
]
908
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
526
909
527
910
[[package]]
528
911
name = "hex"
···
558
941
]
559
942
560
943
[[package]]
944
+
name = "hostname"
945
+
version = "0.4.1"
946
+
source = "registry+https://github.com/rust-lang/crates.io-index"
947
+
checksum = "a56f203cd1c76362b69e3863fd987520ac36cf70a8c92627449b2f64a8cf7d65"
948
+
dependencies = [
949
+
"cfg-if",
950
+
"libc",
951
+
"windows-link",
952
+
]
953
+
954
+
[[package]]
561
955
name = "http"
562
956
version = "1.3.1"
563
957
source = "registry+https://github.com/rust-lang/crates.io-index"
···
612
1006
"bytes",
613
1007
"futures-channel",
614
1008
"futures-util",
1009
+
"h2",
615
1010
"http",
616
1011
"http-body",
617
1012
"httparse",
···
620
1015
"pin-project-lite",
621
1016
"smallvec",
622
1017
"tokio",
1018
+
"want",
1019
+
]
1020
+
1021
+
[[package]]
1022
+
name = "hyper-timeout"
1023
+
version = "0.5.2"
1024
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1025
+
checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0"
1026
+
dependencies = [
1027
+
"hyper",
1028
+
"hyper-util",
1029
+
"pin-project-lite",
1030
+
"tokio",
1031
+
"tower-service",
623
1032
]
624
1033
625
1034
[[package]]
···
629
1038
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
630
1039
dependencies = [
631
1040
"bytes",
1041
+
"futures-channel",
632
1042
"futures-core",
1043
+
"futures-util",
633
1044
"http",
634
1045
"http-body",
635
1046
"hyper",
1047
+
"libc",
636
1048
"pin-project-lite",
1049
+
"socket2",
637
1050
"tokio",
638
1051
"tower-service",
1052
+
"tracing",
1053
+
]
1054
+
1055
+
[[package]]
1056
+
name = "iana-time-zone"
1057
+
version = "0.1.63"
1058
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1059
+
checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
1060
+
dependencies = [
1061
+
"android_system_properties",
1062
+
"core-foundation-sys",
1063
+
"iana-time-zone-haiku",
1064
+
"js-sys",
1065
+
"log",
1066
+
"wasm-bindgen",
1067
+
"windows-core",
1068
+
]
1069
+
1070
+
[[package]]
1071
+
name = "iana-time-zone-haiku"
1072
+
version = "0.1.2"
1073
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1074
+
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
1075
+
dependencies = [
1076
+
"cc",
639
1077
]
640
1078
641
1079
[[package]]
···
725
1163
]
726
1164
727
1165
[[package]]
1166
+
name = "ident_case"
1167
+
version = "1.0.1"
1168
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1169
+
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
1170
+
1171
+
[[package]]
728
1172
name = "idna"
729
1173
version = "1.0.3"
730
1174
source = "registry+https://github.com/rust-lang/crates.io-index"
···
756
1200
]
757
1201
758
1202
[[package]]
1203
+
name = "inout"
1204
+
version = "0.1.4"
1205
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1206
+
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
1207
+
dependencies = [
1208
+
"generic-array",
1209
+
]
1210
+
1211
+
[[package]]
759
1212
name = "io-uring"
760
1213
version = "0.7.9"
761
1214
source = "registry+https://github.com/rust-lang/crates.io-index"
···
773
1226
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
774
1227
775
1228
[[package]]
1229
+
name = "jobserver"
1230
+
version = "0.1.33"
1231
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1232
+
checksum = "38f262f097c174adebe41eb73d66ae9c06b2844fb0da69969647bbddd9b0538a"
1233
+
dependencies = [
1234
+
"getrandom 0.3.3",
1235
+
"libc",
1236
+
]
1237
+
1238
+
[[package]]
1239
+
name = "js-sys"
1240
+
version = "0.3.77"
1241
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1242
+
checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
1243
+
dependencies = [
1244
+
"once_cell",
1245
+
"wasm-bindgen",
1246
+
]
1247
+
1248
+
[[package]]
1249
+
name = "jwt-compact"
1250
+
version = "0.8.0"
1251
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1252
+
checksum = "25cb2458ca54de48ef237ac0d68d4e80e512ae81d6aeb9775f4c835da0d193d3"
1253
+
dependencies = [
1254
+
"anyhow",
1255
+
"base64ct",
1256
+
"chrono",
1257
+
"ciborium",
1258
+
"hmac",
1259
+
"lazy_static",
1260
+
"rand_core 0.6.4",
1261
+
"secp256k1",
1262
+
"serde",
1263
+
"serde_json",
1264
+
"sha2",
1265
+
"smallvec",
1266
+
"subtle",
1267
+
"zeroize",
1268
+
]
1269
+
1270
+
[[package]]
776
1271
name = "lazy_static"
777
1272
version = "1.5.0"
778
1273
source = "registry+https://github.com/rust-lang/crates.io-index"
···
782
1277
]
783
1278
784
1279
[[package]]
1280
+
name = "lettre"
1281
+
version = "0.11.18"
1282
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1283
+
checksum = "5cb54db6ff7a89efac87dba5baeac57bb9ccd726b49a9b6f21fb92b3966aaf56"
1284
+
dependencies = [
1285
+
"async-trait",
1286
+
"base64",
1287
+
"chumsky",
1288
+
"email-encoding",
1289
+
"email_address",
1290
+
"fastrand",
1291
+
"futures-io",
1292
+
"futures-util",
1293
+
"hostname",
1294
+
"httpdate",
1295
+
"idna",
1296
+
"mime",
1297
+
"native-tls",
1298
+
"nom",
1299
+
"percent-encoding",
1300
+
"quoted_printable",
1301
+
"socket2",
1302
+
"tokio",
1303
+
"tokio-native-tls",
1304
+
"url",
1305
+
]
1306
+
1307
+
[[package]]
785
1308
name = "libc"
786
1309
version = "0.2.175"
787
1310
source = "registry+https://github.com/rust-lang/crates.io-index"
···
806
1329
807
1330
[[package]]
808
1331
name = "libsqlite3-sys"
809
-
version = "0.27.0"
1332
+
version = "0.30.1"
810
1333
source = "registry+https://github.com/rust-lang/crates.io-index"
811
-
checksum = "cf4e226dcd58b4be396f7bd3c20da8fdee2911400705297ba7d2d7cc2c30f716"
1334
+
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
812
1335
dependencies = [
813
1336
"cc",
814
1337
"pkg-config",
···
854
1377
855
1378
[[package]]
856
1379
name = "matchit"
857
-
version = "0.7.3"
1380
+
version = "0.8.4"
858
1381
source = "registry+https://github.com/rust-lang/crates.io-index"
859
-
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
1382
+
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
860
1383
861
1384
[[package]]
862
1385
name = "md-5"
···
881
1404
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
882
1405
883
1406
[[package]]
884
-
name = "minimal-lexical"
885
-
version = "0.2.1"
886
-
source = "registry+https://github.com/rust-lang/crates.io-index"
887
-
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
888
-
889
-
[[package]]
890
1407
name = "miniz_oxide"
891
1408
version = "0.8.9"
892
1409
source = "registry+https://github.com/rust-lang/crates.io-index"
···
907
1424
]
908
1425
909
1426
[[package]]
1427
+
name = "native-tls"
1428
+
version = "0.2.14"
1429
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1430
+
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
1431
+
dependencies = [
1432
+
"libc",
1433
+
"log",
1434
+
"openssl",
1435
+
"openssl-probe",
1436
+
"openssl-sys",
1437
+
"schannel",
1438
+
"security-framework",
1439
+
"security-framework-sys",
1440
+
"tempfile",
1441
+
]
1442
+
1443
+
[[package]]
910
1444
name = "nom"
911
-
version = "7.1.3"
1445
+
version = "8.0.0"
912
1446
source = "registry+https://github.com/rust-lang/crates.io-index"
913
-
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
1447
+
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
914
1448
dependencies = [
915
1449
"memchr",
916
-
"minimal-lexical",
917
1450
]
918
1451
919
1452
[[package]]
1453
+
name = "nonempty"
1454
+
version = "0.7.0"
1455
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1456
+
checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7"
1457
+
1458
+
[[package]]
1459
+
name = "nonzero_ext"
1460
+
version = "0.3.0"
1461
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1462
+
checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21"
1463
+
1464
+
[[package]]
920
1465
name = "nu-ansi-term"
921
1466
version = "0.46.0"
922
1467
source = "registry+https://github.com/rust-lang/crates.io-index"
···
938
1483
"num-integer",
939
1484
"num-iter",
940
1485
"num-traits",
941
-
"rand",
1486
+
"rand 0.8.5",
942
1487
"smallvec",
943
1488
"zeroize",
944
1489
]
···
964
1509
]
965
1510
966
1511
[[package]]
1512
+
name = "num-modular"
1513
+
version = "0.6.1"
1514
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1515
+
checksum = "17bb261bf36fa7d83f4c294f834e91256769097b3cb505d44831e0a179ac647f"
1516
+
1517
+
[[package]]
1518
+
name = "num-order"
1519
+
version = "1.2.0"
1520
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1521
+
checksum = "537b596b97c40fcf8056d153049eb22f481c17ebce72a513ec9286e4986d1bb6"
1522
+
dependencies = [
1523
+
"num-modular",
1524
+
]
1525
+
1526
+
[[package]]
967
1527
name = "num-traits"
968
1528
version = "0.2.19"
969
1529
source = "registry+https://github.com/rust-lang/crates.io-index"
···
989
1549
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
990
1550
991
1551
[[package]]
1552
+
name = "openssl"
1553
+
version = "0.10.73"
1554
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1555
+
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
1556
+
dependencies = [
1557
+
"bitflags",
1558
+
"cfg-if",
1559
+
"foreign-types",
1560
+
"libc",
1561
+
"once_cell",
1562
+
"openssl-macros",
1563
+
"openssl-sys",
1564
+
]
1565
+
1566
+
[[package]]
1567
+
name = "openssl-macros"
1568
+
version = "0.1.1"
1569
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1570
+
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
1571
+
dependencies = [
1572
+
"proc-macro2",
1573
+
"quote",
1574
+
"syn",
1575
+
]
1576
+
1577
+
[[package]]
1578
+
name = "openssl-probe"
1579
+
version = "0.1.6"
1580
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1581
+
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
1582
+
1583
+
[[package]]
1584
+
name = "openssl-sys"
1585
+
version = "0.9.109"
1586
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1587
+
checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571"
1588
+
dependencies = [
1589
+
"cc",
1590
+
"libc",
1591
+
"pkg-config",
1592
+
"vcpkg",
1593
+
]
1594
+
1595
+
[[package]]
992
1596
name = "overload"
993
1597
version = "0.1.1"
994
1598
source = "registry+https://github.com/rust-lang/crates.io-index"
995
1599
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
1600
+
1601
+
[[package]]
1602
+
name = "parking"
1603
+
version = "2.2.1"
1604
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1605
+
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
996
1606
997
1607
[[package]]
998
1608
name = "parking_lot"
···
1018
1628
]
1019
1629
1020
1630
[[package]]
1021
-
name = "paste"
1022
-
version = "1.0.15"
1631
+
name = "password-hash"
1632
+
version = "0.5.0"
1633
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1634
+
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
1635
+
dependencies = [
1636
+
"base64ct",
1637
+
"rand_core 0.6.4",
1638
+
"subtle",
1639
+
]
1640
+
1641
+
[[package]]
1642
+
name = "pbkdf2"
1643
+
version = "0.12.2"
1023
1644
source = "registry+https://github.com/rust-lang/crates.io-index"
1024
-
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
1645
+
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
1646
+
dependencies = [
1647
+
"digest",
1648
+
"hmac",
1649
+
]
1025
1650
1026
1651
[[package]]
1027
-
name = "pds_bells_and_whistles"
1652
+
name = "pds_gatekeeper"
1028
1653
version = "0.1.0"
1029
1654
dependencies = [
1030
1655
"axum",
1656
+
"axum-template",
1031
1657
"dotenvy",
1658
+
"handlebars",
1659
+
"hex",
1660
+
"hyper-util",
1661
+
"jwt-compact",
1662
+
"lettre",
1663
+
"rust-embed",
1664
+
"scrypt",
1032
1665
"serde",
1033
1666
"serde_json",
1034
1667
"sqlx",
1035
1668
"tokio",
1669
+
"tower-http",
1670
+
"tower_governor",
1036
1671
"tracing",
1037
1672
"tracing-subscriber",
1038
1673
]
···
1053
1688
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
1054
1689
1055
1690
[[package]]
1691
+
name = "pest"
1692
+
version = "2.8.1"
1693
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1694
+
checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323"
1695
+
dependencies = [
1696
+
"memchr",
1697
+
"thiserror 2.0.14",
1698
+
"ucd-trie",
1699
+
]
1700
+
1701
+
[[package]]
1702
+
name = "pest_derive"
1703
+
version = "2.8.1"
1704
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1705
+
checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc"
1706
+
dependencies = [
1707
+
"pest",
1708
+
"pest_generator",
1709
+
]
1710
+
1711
+
[[package]]
1712
+
name = "pest_generator"
1713
+
version = "2.8.1"
1714
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1715
+
checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966"
1716
+
dependencies = [
1717
+
"pest",
1718
+
"pest_meta",
1719
+
"proc-macro2",
1720
+
"quote",
1721
+
"syn",
1722
+
]
1723
+
1724
+
[[package]]
1725
+
name = "pest_meta"
1726
+
version = "2.8.1"
1727
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1728
+
checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5"
1729
+
dependencies = [
1730
+
"pest",
1731
+
"sha2",
1732
+
]
1733
+
1734
+
[[package]]
1735
+
name = "pin-project"
1736
+
version = "1.1.10"
1737
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1738
+
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
1739
+
dependencies = [
1740
+
"pin-project-internal",
1741
+
]
1742
+
1743
+
[[package]]
1744
+
name = "pin-project-internal"
1745
+
version = "1.1.10"
1746
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1747
+
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
1748
+
dependencies = [
1749
+
"proc-macro2",
1750
+
"quote",
1751
+
"syn",
1752
+
]
1753
+
1754
+
[[package]]
1056
1755
name = "pin-project-lite"
1057
1756
version = "0.2.16"
1058
1757
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1092
1791
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
1093
1792
1094
1793
[[package]]
1794
+
name = "portable-atomic"
1795
+
version = "1.11.1"
1796
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1797
+
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
1798
+
1799
+
[[package]]
1095
1800
name = "potential_utf"
1096
1801
version = "0.1.2"
1097
1802
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1119
1824
]
1120
1825
1121
1826
[[package]]
1827
+
name = "psm"
1828
+
version = "0.1.26"
1829
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1830
+
checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f"
1831
+
dependencies = [
1832
+
"cc",
1833
+
]
1834
+
1835
+
[[package]]
1836
+
name = "quanta"
1837
+
version = "0.12.6"
1838
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1839
+
checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7"
1840
+
dependencies = [
1841
+
"crossbeam-utils",
1842
+
"libc",
1843
+
"once_cell",
1844
+
"raw-cpuid",
1845
+
"wasi 0.11.1+wasi-snapshot-preview1",
1846
+
"web-sys",
1847
+
"winapi",
1848
+
]
1849
+
1850
+
[[package]]
1122
1851
name = "quote"
1123
1852
version = "1.0.40"
1124
1853
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1128
1857
]
1129
1858
1130
1859
[[package]]
1860
+
name = "quoted_printable"
1861
+
version = "0.5.1"
1862
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1863
+
checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73"
1864
+
1865
+
[[package]]
1131
1866
name = "r-efi"
1132
1867
version = "5.3.0"
1133
1868
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1140
1875
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1141
1876
dependencies = [
1142
1877
"libc",
1143
-
"rand_chacha",
1144
-
"rand_core",
1878
+
"rand_chacha 0.3.1",
1879
+
"rand_core 0.6.4",
1880
+
]
1881
+
1882
+
[[package]]
1883
+
name = "rand"
1884
+
version = "0.9.2"
1885
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1886
+
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
1887
+
dependencies = [
1888
+
"rand_chacha 0.9.0",
1889
+
"rand_core 0.9.3",
1145
1890
]
1146
1891
1147
1892
[[package]]
···
1151
1896
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
1152
1897
dependencies = [
1153
1898
"ppv-lite86",
1154
-
"rand_core",
1899
+
"rand_core 0.6.4",
1900
+
]
1901
+
1902
+
[[package]]
1903
+
name = "rand_chacha"
1904
+
version = "0.9.0"
1905
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1906
+
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
1907
+
dependencies = [
1908
+
"ppv-lite86",
1909
+
"rand_core 0.9.3",
1155
1910
]
1156
1911
1157
1912
[[package]]
···
1161
1916
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1162
1917
dependencies = [
1163
1918
"getrandom 0.2.16",
1919
+
]
1920
+
1921
+
[[package]]
1922
+
name = "rand_core"
1923
+
version = "0.9.3"
1924
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1925
+
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
1926
+
dependencies = [
1927
+
"getrandom 0.3.3",
1928
+
]
1929
+
1930
+
[[package]]
1931
+
name = "raw-cpuid"
1932
+
version = "11.5.0"
1933
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1934
+
checksum = "c6df7ab838ed27997ba19a4664507e6f82b41fe6e20be42929332156e5e85146"
1935
+
dependencies = [
1936
+
"bitflags",
1164
1937
]
1165
1938
1166
1939
[[package]]
···
1243
2016
"num-traits",
1244
2017
"pkcs1",
1245
2018
"pkcs8",
1246
-
"rand_core",
2019
+
"rand_core 0.6.4",
1247
2020
"signature",
1248
2021
"spki",
1249
2022
"subtle",
···
1251
2024
]
1252
2025
1253
2026
[[package]]
2027
+
name = "rust-embed"
2028
+
version = "8.7.2"
2029
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2030
+
checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a"
2031
+
dependencies = [
2032
+
"rust-embed-impl",
2033
+
"rust-embed-utils",
2034
+
"walkdir",
2035
+
]
2036
+
2037
+
[[package]]
2038
+
name = "rust-embed-impl"
2039
+
version = "8.7.2"
2040
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2041
+
checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c"
2042
+
dependencies = [
2043
+
"proc-macro2",
2044
+
"quote",
2045
+
"rust-embed-utils",
2046
+
"syn",
2047
+
"walkdir",
2048
+
]
2049
+
2050
+
[[package]]
2051
+
name = "rust-embed-utils"
2052
+
version = "8.7.2"
2053
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2054
+
checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594"
2055
+
dependencies = [
2056
+
"globset",
2057
+
"sha2",
2058
+
"walkdir",
2059
+
]
2060
+
2061
+
[[package]]
1254
2062
name = "rustc-demangle"
1255
2063
version = "0.1.26"
1256
2064
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1266
2074
"errno",
1267
2075
"libc",
1268
2076
"linux-raw-sys",
1269
-
"windows-sys 0.60.2",
2077
+
"windows-sys 0.59.0",
1270
2078
]
1271
2079
1272
2080
[[package]]
1273
2081
name = "rustls"
1274
-
version = "0.21.12"
2082
+
version = "0.23.31"
1275
2083
source = "registry+https://github.com/rust-lang/crates.io-index"
1276
-
checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e"
2084
+
checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc"
1277
2085
dependencies = [
2086
+
"once_cell",
1278
2087
"ring",
2088
+
"rustls-pki-types",
1279
2089
"rustls-webpki",
1280
-
"sct",
2090
+
"subtle",
2091
+
"zeroize",
1281
2092
]
1282
2093
1283
2094
[[package]]
1284
-
name = "rustls-pemfile"
1285
-
version = "1.0.4"
2095
+
name = "rustls-pki-types"
2096
+
version = "1.12.0"
1286
2097
source = "registry+https://github.com/rust-lang/crates.io-index"
1287
-
checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c"
2098
+
checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79"
1288
2099
dependencies = [
1289
-
"base64",
2100
+
"zeroize",
1290
2101
]
1291
2102
1292
2103
[[package]]
1293
2104
name = "rustls-webpki"
1294
-
version = "0.101.7"
2105
+
version = "0.103.4"
1295
2106
source = "registry+https://github.com/rust-lang/crates.io-index"
1296
-
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765"
2107
+
checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc"
1297
2108
dependencies = [
1298
2109
"ring",
2110
+
"rustls-pki-types",
1299
2111
"untrusted",
1300
2112
]
1301
2113
···
1312
2124
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
1313
2125
1314
2126
[[package]]
2127
+
name = "salsa20"
2128
+
version = "0.10.2"
2129
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2130
+
checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
2131
+
dependencies = [
2132
+
"cipher",
2133
+
]
2134
+
2135
+
[[package]]
2136
+
name = "same-file"
2137
+
version = "1.0.6"
2138
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2139
+
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
2140
+
dependencies = [
2141
+
"winapi-util",
2142
+
]
2143
+
2144
+
[[package]]
2145
+
name = "schannel"
2146
+
version = "0.1.27"
2147
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2148
+
checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
2149
+
dependencies = [
2150
+
"windows-sys 0.59.0",
2151
+
]
2152
+
2153
+
[[package]]
1315
2154
name = "scopeguard"
1316
2155
version = "1.2.0"
1317
2156
source = "registry+https://github.com/rust-lang/crates.io-index"
1318
2157
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1319
2158
1320
2159
[[package]]
1321
-
name = "sct"
1322
-
version = "0.7.1"
2160
+
name = "scrypt"
2161
+
version = "0.11.0"
2162
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2163
+
checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
2164
+
dependencies = [
2165
+
"password-hash",
2166
+
"pbkdf2",
2167
+
"salsa20",
2168
+
"sha2",
2169
+
]
2170
+
2171
+
[[package]]
2172
+
name = "secp256k1"
2173
+
version = "0.28.2"
2174
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2175
+
checksum = "d24b59d129cdadea20aea4fb2352fa053712e5d713eee47d700cd4b2bc002f10"
2176
+
dependencies = [
2177
+
"secp256k1-sys",
2178
+
]
2179
+
2180
+
[[package]]
2181
+
name = "secp256k1-sys"
2182
+
version = "0.9.2"
2183
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2184
+
checksum = "e5d1746aae42c19d583c3c1a8c646bfad910498e2051c551a7f2e3c0c9fbb7eb"
2185
+
dependencies = [
2186
+
"cc",
2187
+
]
2188
+
2189
+
[[package]]
2190
+
name = "security-framework"
2191
+
version = "2.11.1"
2192
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2193
+
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
2194
+
dependencies = [
2195
+
"bitflags",
2196
+
"core-foundation",
2197
+
"core-foundation-sys",
2198
+
"libc",
2199
+
"security-framework-sys",
2200
+
]
2201
+
2202
+
[[package]]
2203
+
name = "security-framework-sys"
2204
+
version = "2.14.0"
1323
2205
source = "registry+https://github.com/rust-lang/crates.io-index"
1324
-
checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414"
2206
+
checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
1325
2207
dependencies = [
1326
-
"ring",
1327
-
"untrusted",
2208
+
"core-foundation-sys",
2209
+
"libc",
1328
2210
]
1329
2211
1330
2212
[[package]]
···
1344
2226
dependencies = [
1345
2227
"proc-macro2",
1346
2228
"quote",
1347
-
"syn 2.0.105",
2229
+
"syn",
1348
2230
]
1349
2231
1350
2232
[[package]]
···
1434
2316
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
1435
2317
dependencies = [
1436
2318
"digest",
1437
-
"rand_core",
2319
+
"rand_core 0.6.4",
1438
2320
]
1439
2321
1440
2322
[[package]]
···
1448
2330
version = "1.15.1"
1449
2331
source = "registry+https://github.com/rust-lang/crates.io-index"
1450
2332
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
2333
+
dependencies = [
2334
+
"serde",
2335
+
]
1451
2336
1452
2337
[[package]]
1453
2338
name = "socket2"
···
1469
2354
]
1470
2355
1471
2356
[[package]]
2357
+
name = "spinning_top"
2358
+
version = "0.3.0"
2359
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2360
+
checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300"
2361
+
dependencies = [
2362
+
"lock_api",
2363
+
]
2364
+
2365
+
[[package]]
1472
2366
name = "spki"
1473
2367
version = "0.7.3"
1474
2368
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1479
2373
]
1480
2374
1481
2375
[[package]]
1482
-
name = "sqlformat"
1483
-
version = "0.2.6"
1484
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1485
-
checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790"
1486
-
dependencies = [
1487
-
"nom",
1488
-
"unicode_categories",
1489
-
]
1490
-
1491
-
[[package]]
1492
2376
name = "sqlx"
1493
-
version = "0.7.4"
2377
+
version = "0.8.6"
1494
2378
source = "registry+https://github.com/rust-lang/crates.io-index"
1495
-
checksum = "c9a2ccff1a000a5a59cd33da541d9f2fdcd9e6e8229cc200565942bff36d0aaa"
2379
+
checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc"
1496
2380
dependencies = [
1497
2381
"sqlx-core",
1498
2382
"sqlx-macros",
···
1503
2387
1504
2388
[[package]]
1505
2389
name = "sqlx-core"
1506
-
version = "0.7.4"
2390
+
version = "0.8.6"
1507
2391
source = "registry+https://github.com/rust-lang/crates.io-index"
1508
-
checksum = "24ba59a9342a3d9bab6c56c118be528b27c9b60e490080e9711a04dccac83ef6"
2392
+
checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
1509
2393
dependencies = [
1510
-
"ahash",
1511
-
"atoi",
1512
-
"byteorder",
2394
+
"base64",
1513
2395
"bytes",
1514
2396
"crc",
1515
2397
"crossbeam-queue",
1516
2398
"either",
1517
2399
"event-listener",
1518
-
"futures-channel",
1519
2400
"futures-core",
1520
2401
"futures-intrusive",
1521
2402
"futures-io",
1522
2403
"futures-util",
2404
+
"hashbrown 0.15.5",
1523
2405
"hashlink",
1524
-
"hex",
1525
2406
"indexmap",
1526
2407
"log",
1527
2408
"memchr",
1528
2409
"once_cell",
1529
-
"paste",
1530
2410
"percent-encoding",
1531
2411
"rustls",
1532
-
"rustls-pemfile",
1533
2412
"serde",
1534
2413
"serde_json",
1535
2414
"sha2",
1536
2415
"smallvec",
1537
-
"sqlformat",
1538
-
"thiserror",
2416
+
"thiserror 2.0.14",
1539
2417
"tokio",
1540
2418
"tokio-stream",
1541
2419
"tracing",
1542
2420
"url",
1543
-
"webpki-roots",
2421
+
"webpki-roots 0.26.11",
1544
2422
]
1545
2423
1546
2424
[[package]]
1547
2425
name = "sqlx-macros"
1548
-
version = "0.7.4"
2426
+
version = "0.8.6"
1549
2427
source = "registry+https://github.com/rust-lang/crates.io-index"
1550
-
checksum = "4ea40e2345eb2faa9e1e5e326db8c34711317d2b5e08d0d5741619048a803127"
2428
+
checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d"
1551
2429
dependencies = [
1552
2430
"proc-macro2",
1553
2431
"quote",
1554
2432
"sqlx-core",
1555
2433
"sqlx-macros-core",
1556
-
"syn 1.0.109",
2434
+
"syn",
1557
2435
]
1558
2436
1559
2437
[[package]]
1560
2438
name = "sqlx-macros-core"
1561
-
version = "0.7.4"
2439
+
version = "0.8.6"
1562
2440
source = "registry+https://github.com/rust-lang/crates.io-index"
1563
-
checksum = "5833ef53aaa16d860e92123292f1f6a3d53c34ba8b1969f152ef1a7bb803f3c8"
2441
+
checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b"
1564
2442
dependencies = [
1565
2443
"dotenvy",
1566
2444
"either",
···
1574
2452
"sha2",
1575
2453
"sqlx-core",
1576
2454
"sqlx-mysql",
2455
+
"sqlx-postgres",
1577
2456
"sqlx-sqlite",
1578
-
"syn 1.0.109",
1579
-
"tempfile",
2457
+
"syn",
1580
2458
"tokio",
1581
2459
"url",
1582
2460
]
1583
2461
1584
2462
[[package]]
1585
2463
name = "sqlx-mysql"
1586
-
version = "0.7.4"
2464
+
version = "0.8.6"
1587
2465
source = "registry+https://github.com/rust-lang/crates.io-index"
1588
-
checksum = "1ed31390216d20e538e447a7a9b959e06ed9fc51c37b514b46eb758016ecd418"
2466
+
checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
1589
2467
dependencies = [
1590
2468
"atoi",
1591
2469
"base64",
···
1610
2488
"memchr",
1611
2489
"once_cell",
1612
2490
"percent-encoding",
1613
-
"rand",
2491
+
"rand 0.8.5",
1614
2492
"rsa",
1615
2493
"serde",
1616
2494
"sha1",
···
1618
2496
"smallvec",
1619
2497
"sqlx-core",
1620
2498
"stringprep",
1621
-
"thiserror",
2499
+
"thiserror 2.0.14",
1622
2500
"tracing",
1623
2501
"whoami",
1624
2502
]
1625
2503
1626
2504
[[package]]
1627
2505
name = "sqlx-postgres"
1628
-
version = "0.7.4"
2506
+
version = "0.8.6"
1629
2507
source = "registry+https://github.com/rust-lang/crates.io-index"
1630
-
checksum = "7c824eb80b894f926f89a0b9da0c7f435d27cdd35b8c655b114e58223918577e"
2508
+
checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
1631
2509
dependencies = [
1632
2510
"atoi",
1633
2511
"base64",
···
1638
2516
"etcetera",
1639
2517
"futures-channel",
1640
2518
"futures-core",
1641
-
"futures-io",
1642
2519
"futures-util",
1643
2520
"hex",
1644
2521
"hkdf",
···
1649
2526
"md-5",
1650
2527
"memchr",
1651
2528
"once_cell",
1652
-
"rand",
2529
+
"rand 0.8.5",
1653
2530
"serde",
1654
2531
"serde_json",
1655
2532
"sha2",
1656
2533
"smallvec",
1657
2534
"sqlx-core",
1658
2535
"stringprep",
1659
-
"thiserror",
2536
+
"thiserror 2.0.14",
1660
2537
"tracing",
1661
2538
"whoami",
1662
2539
]
1663
2540
1664
2541
[[package]]
1665
2542
name = "sqlx-sqlite"
1666
-
version = "0.7.4"
2543
+
version = "0.8.6"
1667
2544
source = "registry+https://github.com/rust-lang/crates.io-index"
1668
-
checksum = "b244ef0a8414da0bed4bb1910426e890b19e5e9bccc27ada6b797d05c55ae0aa"
2545
+
checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
1669
2546
dependencies = [
1670
2547
"atoi",
1671
2548
"flume",
···
1678
2555
"log",
1679
2556
"percent-encoding",
1680
2557
"serde",
2558
+
"serde_urlencoded",
1681
2559
"sqlx-core",
2560
+
"thiserror 2.0.14",
1682
2561
"tracing",
1683
2562
"url",
1684
-
"urlencoding",
1685
2563
]
1686
2564
1687
2565
[[package]]
···
1691
2569
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
1692
2570
1693
2571
[[package]]
2572
+
name = "stacker"
2573
+
version = "0.1.21"
2574
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2575
+
checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b"
2576
+
dependencies = [
2577
+
"cc",
2578
+
"cfg-if",
2579
+
"libc",
2580
+
"psm",
2581
+
"windows-sys 0.59.0",
2582
+
]
2583
+
2584
+
[[package]]
1694
2585
name = "stringprep"
1695
2586
version = "0.1.5"
1696
2587
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1702
2593
]
1703
2594
1704
2595
[[package]]
2596
+
name = "strsim"
2597
+
version = "0.11.1"
2598
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2599
+
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
2600
+
2601
+
[[package]]
1705
2602
name = "subtle"
1706
2603
version = "2.6.1"
1707
2604
source = "registry+https://github.com/rust-lang/crates.io-index"
1708
2605
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
1709
-
1710
-
[[package]]
1711
-
name = "syn"
1712
-
version = "1.0.109"
1713
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1714
-
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
1715
-
dependencies = [
1716
-
"proc-macro2",
1717
-
"quote",
1718
-
"unicode-ident",
1719
-
]
1720
2606
1721
2607
[[package]]
1722
2608
name = "syn"
···
1743
2629
dependencies = [
1744
2630
"proc-macro2",
1745
2631
"quote",
1746
-
"syn 2.0.105",
2632
+
"syn",
1747
2633
]
1748
2634
1749
2635
[[package]]
1750
2636
name = "tempfile"
1751
-
version = "3.20.0"
2637
+
version = "3.21.0"
1752
2638
source = "registry+https://github.com/rust-lang/crates.io-index"
1753
-
checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1"
2639
+
checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e"
1754
2640
dependencies = [
1755
2641
"fastrand",
1756
2642
"getrandom 0.3.3",
···
1765
2651
source = "registry+https://github.com/rust-lang/crates.io-index"
1766
2652
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
1767
2653
dependencies = [
1768
-
"thiserror-impl",
2654
+
"thiserror-impl 1.0.69",
2655
+
]
2656
+
2657
+
[[package]]
2658
+
name = "thiserror"
2659
+
version = "2.0.14"
2660
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2661
+
checksum = "0b0949c3a6c842cbde3f1686d6eea5a010516deb7085f79db747562d4102f41e"
2662
+
dependencies = [
2663
+
"thiserror-impl 2.0.14",
1769
2664
]
1770
2665
1771
2666
[[package]]
···
1776
2671
dependencies = [
1777
2672
"proc-macro2",
1778
2673
"quote",
1779
-
"syn 2.0.105",
2674
+
"syn",
2675
+
]
2676
+
2677
+
[[package]]
2678
+
name = "thiserror-impl"
2679
+
version = "2.0.14"
2680
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2681
+
checksum = "cc5b44b4ab9c2fdd0e0512e6bece8388e214c0749f5862b114cc5b7a25daf227"
2682
+
dependencies = [
2683
+
"proc-macro2",
2684
+
"quote",
2685
+
"syn",
1780
2686
]
1781
2687
1782
2688
[[package]]
···
1840
2746
dependencies = [
1841
2747
"proc-macro2",
1842
2748
"quote",
1843
-
"syn 2.0.105",
2749
+
"syn",
2750
+
]
2751
+
2752
+
[[package]]
2753
+
name = "tokio-native-tls"
2754
+
version = "0.3.1"
2755
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2756
+
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
2757
+
dependencies = [
2758
+
"native-tls",
2759
+
"tokio",
1844
2760
]
1845
2761
1846
2762
[[package]]
···
1855
2771
]
1856
2772
1857
2773
[[package]]
2774
+
name = "tokio-util"
2775
+
version = "0.7.15"
2776
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2777
+
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df"
2778
+
dependencies = [
2779
+
"bytes",
2780
+
"futures-core",
2781
+
"futures-sink",
2782
+
"pin-project-lite",
2783
+
"tokio",
2784
+
]
2785
+
2786
+
[[package]]
2787
+
name = "tonic"
2788
+
version = "0.14.1"
2789
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2790
+
checksum = "67ac5a8627ada0968acec063a4746bf79588aa03ccb66db2f75d7dce26722a40"
2791
+
dependencies = [
2792
+
"async-trait",
2793
+
"axum",
2794
+
"base64",
2795
+
"bytes",
2796
+
"h2",
2797
+
"http",
2798
+
"http-body",
2799
+
"http-body-util",
2800
+
"hyper",
2801
+
"hyper-timeout",
2802
+
"hyper-util",
2803
+
"percent-encoding",
2804
+
"pin-project",
2805
+
"socket2",
2806
+
"sync_wrapper",
2807
+
"tokio",
2808
+
"tokio-stream",
2809
+
"tower",
2810
+
"tower-layer",
2811
+
"tower-service",
2812
+
"tracing",
2813
+
]
2814
+
2815
+
[[package]]
1858
2816
name = "tower"
1859
2817
version = "0.5.2"
1860
2818
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1862
2820
dependencies = [
1863
2821
"futures-core",
1864
2822
"futures-util",
2823
+
"indexmap",
1865
2824
"pin-project-lite",
2825
+
"slab",
1866
2826
"sync_wrapper",
1867
2827
"tokio",
2828
+
"tokio-util",
1868
2829
"tower-layer",
1869
2830
"tower-service",
1870
2831
"tracing",
1871
2832
]
1872
2833
1873
2834
[[package]]
2835
+
name = "tower-http"
2836
+
version = "0.6.6"
2837
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2838
+
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
2839
+
dependencies = [
2840
+
"async-compression",
2841
+
"bitflags",
2842
+
"bytes",
2843
+
"futures-core",
2844
+
"http",
2845
+
"http-body",
2846
+
"pin-project-lite",
2847
+
"tokio",
2848
+
"tokio-util",
2849
+
"tower-layer",
2850
+
"tower-service",
2851
+
]
2852
+
2853
+
[[package]]
1874
2854
name = "tower-layer"
1875
2855
version = "0.3.3"
1876
2856
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1883
2863
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
1884
2864
1885
2865
[[package]]
2866
+
name = "tower_governor"
2867
+
version = "0.8.0"
2868
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2869
+
checksum = "44de9b94d849d3c46e06a883d72d408c2de6403367b39df2b1c9d9e7b6736fe6"
2870
+
dependencies = [
2871
+
"axum",
2872
+
"forwarded-header-value",
2873
+
"governor",
2874
+
"http",
2875
+
"pin-project",
2876
+
"thiserror 2.0.14",
2877
+
"tonic",
2878
+
"tower",
2879
+
"tracing",
2880
+
]
2881
+
2882
+
[[package]]
1886
2883
name = "tracing"
1887
2884
version = "0.1.41"
1888
2885
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1902
2899
dependencies = [
1903
2900
"proc-macro2",
1904
2901
"quote",
1905
-
"syn 2.0.105",
2902
+
"syn",
1906
2903
]
1907
2904
1908
2905
[[package]]
···
1945
2942
]
1946
2943
1947
2944
[[package]]
2945
+
name = "try-lock"
2946
+
version = "0.2.5"
2947
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2948
+
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
2949
+
2950
+
[[package]]
1948
2951
name = "typenum"
1949
2952
version = "1.18.0"
1950
2953
source = "registry+https://github.com/rust-lang/crates.io-index"
1951
2954
checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
1952
2955
1953
2956
[[package]]
2957
+
name = "ucd-trie"
2958
+
version = "0.1.7"
2959
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2960
+
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
2961
+
2962
+
[[package]]
1954
2963
name = "unicode-bidi"
1955
2964
version = "0.3.18"
1956
2965
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1978
2987
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
1979
2988
1980
2989
[[package]]
1981
-
name = "unicode-segmentation"
1982
-
version = "1.12.0"
1983
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1984
-
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
1985
-
1986
-
[[package]]
1987
-
name = "unicode_categories"
1988
-
version = "0.1.1"
1989
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1990
-
checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e"
1991
-
1992
-
[[package]]
1993
2990
name = "untrusted"
1994
2991
version = "0.9.0"
1995
2992
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2005
3002
"idna",
2006
3003
"percent-encoding",
2007
3004
]
2008
-
2009
-
[[package]]
2010
-
name = "urlencoding"
2011
-
version = "2.1.3"
2012
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2013
-
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
2014
3005
2015
3006
[[package]]
2016
3007
name = "utf8_iter"
···
2037
3028
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
2038
3029
2039
3030
[[package]]
3031
+
name = "walkdir"
3032
+
version = "2.5.0"
3033
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3034
+
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
3035
+
dependencies = [
3036
+
"same-file",
3037
+
"winapi-util",
3038
+
]
3039
+
3040
+
[[package]]
3041
+
name = "want"
3042
+
version = "0.3.1"
3043
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3044
+
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
3045
+
dependencies = [
3046
+
"try-lock",
3047
+
]
3048
+
3049
+
[[package]]
2040
3050
name = "wasi"
2041
3051
version = "0.11.1+wasi-snapshot-preview1"
2042
3052
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2058
3068
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
2059
3069
2060
3070
[[package]]
3071
+
name = "wasm-bindgen"
3072
+
version = "0.2.100"
3073
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3074
+
checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
3075
+
dependencies = [
3076
+
"cfg-if",
3077
+
"once_cell",
3078
+
"rustversion",
3079
+
"wasm-bindgen-macro",
3080
+
]
3081
+
3082
+
[[package]]
3083
+
name = "wasm-bindgen-backend"
3084
+
version = "0.2.100"
3085
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3086
+
checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
3087
+
dependencies = [
3088
+
"bumpalo",
3089
+
"log",
3090
+
"proc-macro2",
3091
+
"quote",
3092
+
"syn",
3093
+
"wasm-bindgen-shared",
3094
+
]
3095
+
3096
+
[[package]]
3097
+
name = "wasm-bindgen-macro"
3098
+
version = "0.2.100"
3099
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3100
+
checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
3101
+
dependencies = [
3102
+
"quote",
3103
+
"wasm-bindgen-macro-support",
3104
+
]
3105
+
3106
+
[[package]]
3107
+
name = "wasm-bindgen-macro-support"
3108
+
version = "0.2.100"
3109
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3110
+
checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
3111
+
dependencies = [
3112
+
"proc-macro2",
3113
+
"quote",
3114
+
"syn",
3115
+
"wasm-bindgen-backend",
3116
+
"wasm-bindgen-shared",
3117
+
]
3118
+
3119
+
[[package]]
3120
+
name = "wasm-bindgen-shared"
3121
+
version = "0.2.100"
3122
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3123
+
checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
3124
+
dependencies = [
3125
+
"unicode-ident",
3126
+
]
3127
+
3128
+
[[package]]
3129
+
name = "web-sys"
3130
+
version = "0.3.77"
3131
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3132
+
checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
3133
+
dependencies = [
3134
+
"js-sys",
3135
+
"wasm-bindgen",
3136
+
]
3137
+
3138
+
[[package]]
3139
+
name = "web-time"
3140
+
version = "1.1.0"
3141
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3142
+
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
3143
+
dependencies = [
3144
+
"js-sys",
3145
+
"wasm-bindgen",
3146
+
]
3147
+
3148
+
[[package]]
2061
3149
name = "webpki-roots"
2062
-
version = "0.25.4"
3150
+
version = "0.26.11"
3151
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3152
+
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
3153
+
dependencies = [
3154
+
"webpki-roots 1.0.2",
3155
+
]
3156
+
3157
+
[[package]]
3158
+
name = "webpki-roots"
3159
+
version = "1.0.2"
2063
3160
source = "registry+https://github.com/rust-lang/crates.io-index"
2064
-
checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1"
3161
+
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
3162
+
dependencies = [
3163
+
"rustls-pki-types",
3164
+
]
2065
3165
2066
3166
[[package]]
2067
3167
name = "whoami"
···
2090
3190
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
2091
3191
2092
3192
[[package]]
3193
+
name = "winapi-util"
3194
+
version = "0.1.9"
3195
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3196
+
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
3197
+
dependencies = [
3198
+
"windows-sys 0.59.0",
3199
+
]
3200
+
3201
+
[[package]]
2093
3202
name = "winapi-x86_64-pc-windows-gnu"
2094
3203
version = "0.4.0"
2095
3204
source = "registry+https://github.com/rust-lang/crates.io-index"
2096
3205
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
2097
3206
2098
3207
[[package]]
3208
+
name = "windows-core"
3209
+
version = "0.61.2"
3210
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3211
+
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
3212
+
dependencies = [
3213
+
"windows-implement",
3214
+
"windows-interface",
3215
+
"windows-link",
3216
+
"windows-result",
3217
+
"windows-strings",
3218
+
]
3219
+
3220
+
[[package]]
3221
+
name = "windows-implement"
3222
+
version = "0.60.0"
3223
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3224
+
checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
3225
+
dependencies = [
3226
+
"proc-macro2",
3227
+
"quote",
3228
+
"syn",
3229
+
]
3230
+
3231
+
[[package]]
3232
+
name = "windows-interface"
3233
+
version = "0.59.1"
3234
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3235
+
checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
3236
+
dependencies = [
3237
+
"proc-macro2",
3238
+
"quote",
3239
+
"syn",
3240
+
]
3241
+
3242
+
[[package]]
2099
3243
name = "windows-link"
2100
3244
version = "0.1.3"
2101
3245
source = "registry+https://github.com/rust-lang/crates.io-index"
2102
3246
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
3247
+
3248
+
[[package]]
3249
+
name = "windows-result"
3250
+
version = "0.3.4"
3251
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3252
+
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
3253
+
dependencies = [
3254
+
"windows-link",
3255
+
]
3256
+
3257
+
[[package]]
3258
+
name = "windows-strings"
3259
+
version = "0.4.2"
3260
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3261
+
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
3262
+
dependencies = [
3263
+
"windows-link",
3264
+
]
2103
3265
2104
3266
[[package]]
2105
3267
name = "windows-sys"
···
2129
3291
]
2130
3292
2131
3293
[[package]]
2132
-
name = "windows-sys"
2133
-
version = "0.60.2"
2134
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2135
-
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
2136
-
dependencies = [
2137
-
"windows-targets 0.53.3",
2138
-
]
2139
-
2140
-
[[package]]
2141
3294
name = "windows-targets"
2142
3295
version = "0.48.5"
2143
3296
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2161
3314
"windows_aarch64_gnullvm 0.52.6",
2162
3315
"windows_aarch64_msvc 0.52.6",
2163
3316
"windows_i686_gnu 0.52.6",
2164
-
"windows_i686_gnullvm 0.52.6",
3317
+
"windows_i686_gnullvm",
2165
3318
"windows_i686_msvc 0.52.6",
2166
3319
"windows_x86_64_gnu 0.52.6",
2167
3320
"windows_x86_64_gnullvm 0.52.6",
2168
3321
"windows_x86_64_msvc 0.52.6",
2169
-
]
2170
-
2171
-
[[package]]
2172
-
name = "windows-targets"
2173
-
version = "0.53.3"
2174
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2175
-
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
2176
-
dependencies = [
2177
-
"windows-link",
2178
-
"windows_aarch64_gnullvm 0.53.0",
2179
-
"windows_aarch64_msvc 0.53.0",
2180
-
"windows_i686_gnu 0.53.0",
2181
-
"windows_i686_gnullvm 0.53.0",
2182
-
"windows_i686_msvc 0.53.0",
2183
-
"windows_x86_64_gnu 0.53.0",
2184
-
"windows_x86_64_gnullvm 0.53.0",
2185
-
"windows_x86_64_msvc 0.53.0",
2186
3322
]
2187
3323
2188
3324
[[package]]
···
2198
3334
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
2199
3335
2200
3336
[[package]]
2201
-
name = "windows_aarch64_gnullvm"
2202
-
version = "0.53.0"
2203
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2204
-
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
2205
-
2206
-
[[package]]
2207
3337
name = "windows_aarch64_msvc"
2208
3338
version = "0.48.5"
2209
3339
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2216
3346
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
2217
3347
2218
3348
[[package]]
2219
-
name = "windows_aarch64_msvc"
2220
-
version = "0.53.0"
2221
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2222
-
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
2223
-
2224
-
[[package]]
2225
3349
name = "windows_i686_gnu"
2226
3350
version = "0.48.5"
2227
3351
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2234
3358
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
2235
3359
2236
3360
[[package]]
2237
-
name = "windows_i686_gnu"
2238
-
version = "0.53.0"
2239
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2240
-
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
2241
-
2242
-
[[package]]
2243
3361
name = "windows_i686_gnullvm"
2244
3362
version = "0.52.6"
2245
3363
source = "registry+https://github.com/rust-lang/crates.io-index"
2246
3364
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
2247
3365
2248
3366
[[package]]
2249
-
name = "windows_i686_gnullvm"
2250
-
version = "0.53.0"
2251
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2252
-
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
2253
-
2254
-
[[package]]
2255
3367
name = "windows_i686_msvc"
2256
3368
version = "0.48.5"
2257
3369
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2264
3376
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
2265
3377
2266
3378
[[package]]
2267
-
name = "windows_i686_msvc"
2268
-
version = "0.53.0"
2269
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2270
-
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
2271
-
2272
-
[[package]]
2273
3379
name = "windows_x86_64_gnu"
2274
3380
version = "0.48.5"
2275
3381
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2282
3388
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
2283
3389
2284
3390
[[package]]
2285
-
name = "windows_x86_64_gnu"
2286
-
version = "0.53.0"
2287
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2288
-
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
2289
-
2290
-
[[package]]
2291
3391
name = "windows_x86_64_gnullvm"
2292
3392
version = "0.48.5"
2293
3393
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2300
3400
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
2301
3401
2302
3402
[[package]]
2303
-
name = "windows_x86_64_gnullvm"
2304
-
version = "0.53.0"
2305
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2306
-
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
2307
-
2308
-
[[package]]
2309
3403
name = "windows_x86_64_msvc"
2310
3404
version = "0.48.5"
2311
3405
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2316
3410
version = "0.52.6"
2317
3411
source = "registry+https://github.com/rust-lang/crates.io-index"
2318
3412
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
2319
-
2320
-
[[package]]
2321
-
name = "windows_x86_64_msvc"
2322
-
version = "0.53.0"
2323
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2324
-
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
2325
3413
2326
3414
[[package]]
2327
3415
name = "wit-bindgen-rt"
···
2358
3446
dependencies = [
2359
3447
"proc-macro2",
2360
3448
"quote",
2361
-
"syn 2.0.105",
3449
+
"syn",
2362
3450
"synstructure",
2363
3451
]
2364
3452
···
2379
3467
dependencies = [
2380
3468
"proc-macro2",
2381
3469
"quote",
2382
-
"syn 2.0.105",
3470
+
"syn",
2383
3471
]
2384
3472
2385
3473
[[package]]
···
2399
3487
dependencies = [
2400
3488
"proc-macro2",
2401
3489
"quote",
2402
-
"syn 2.0.105",
3490
+
"syn",
2403
3491
"synstructure",
2404
3492
]
2405
3493
···
2408
3496
version = "1.8.1"
2409
3497
source = "registry+https://github.com/rust-lang/crates.io-index"
2410
3498
checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
3499
+
dependencies = [
3500
+
"zeroize_derive",
3501
+
]
3502
+
3503
+
[[package]]
3504
+
name = "zeroize_derive"
3505
+
version = "1.4.2"
3506
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3507
+
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
3508
+
dependencies = [
3509
+
"proc-macro2",
3510
+
"quote",
3511
+
"syn",
3512
+
]
2411
3513
2412
3514
[[package]]
2413
3515
name = "zerotrie"
···
2439
3541
dependencies = [
2440
3542
"proc-macro2",
2441
3543
"quote",
2442
-
"syn 2.0.105",
3544
+
"syn",
3545
+
]
3546
+
3547
+
[[package]]
3548
+
name = "zstd"
3549
+
version = "0.13.3"
3550
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3551
+
checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a"
3552
+
dependencies = [
3553
+
"zstd-safe",
3554
+
]
3555
+
3556
+
[[package]]
3557
+
name = "zstd-safe"
3558
+
version = "7.2.4"
3559
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3560
+
checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d"
3561
+
dependencies = [
3562
+
"zstd-sys",
3563
+
]
3564
+
3565
+
[[package]]
3566
+
name = "zstd-sys"
3567
+
version = "2.0.15+zstd.1.5.7"
3568
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3569
+
checksum = "eb81183ddd97d0c74cedf1d50d85c8d08c1b8b68ee863bdee9e706eedba1a237"
3570
+
dependencies = [
3571
+
"cc",
3572
+
"pkg-config",
2443
3573
]
+14
-4
Cargo.toml
+14
-4
Cargo.toml
···
1
1
[package]
2
-
name = "pds_bells_and_whistles"
2
+
name = "pds_gatekeeper"
3
3
version = "0.1.0"
4
4
edition = "2024"
5
5
6
6
[dependencies]
7
-
axum = { version = "0.7", features = ["macros", "json"] }
8
-
tokio = { version = "1.39", features = ["rt-multi-thread", "macros", "signal"] }
9
-
sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "sqlite"] }
7
+
axum = { version = "0.8.4", features = ["macros", "json"] }
8
+
tokio = { version = "1.47.1", features = ["rt-multi-thread", "macros", "signal"] }
9
+
sqlx = { version = "0.8.6", features = ["runtime-tokio-rustls", "sqlite", "migrate"] }
10
10
dotenvy = "0.15.7"
11
11
serde = { version = "1.0", features = ["derive"] }
12
12
serde_json = "1.0"
13
13
tracing = "0.1"
14
14
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
15
+
hyper-util = { version = "0.1.16", features = ["client", "client-legacy"] }
16
+
tower-http = { version = "0.6", features = ["cors", "compression-zstd"] }
17
+
tower_governor = "0.8.0"
18
+
hex = "0.4"
19
+
jwt-compact = { version = "0.8.0", features = ["es256k"] }
20
+
scrypt = "0.11"
21
+
lettre = { version = "0.11.18", features = ["tokio1", "pool", "tokio1-native-tls"] }
22
+
handlebars = { version = "6.3.2", features = ["rust-embed"] }
23
+
rust-embed = "8.7.2"
24
+
axum-template = { version = "3.0.0", features = ["handlebars"] }
+49
README.md
+49
README.md
···
1
+
# PDS gatekeeper
2
+
3
+
A microservice that sits on the same server as the PDS to add some of the security that the entryway does.
4
+
5
+

6
+
7
+
PDS gatekeeper works by overriding some of the PDS endpoints inside your Caddyfile to provide gatekeeping to certain
8
+
endpoints. Mainly, the ability to have 2FA on a self hosted PDS like it does on a Bluesky mushroom(PDS). Most of the
9
+
logic of these endpoints still happens on the PDS via a proxied request, just some are gatekept.
10
+
11
+
# Features
12
+
13
+
## 2FA
14
+
15
+
- [x] Ability to turn on/off 2FA
16
+
- [x] getSession overwrite to set the `emailAuthFactor` flag if the user has 2FA turned on
17
+
- [x] send an email using the `PDS_EMAIL_SMTP_URL` with a handlebar email template like Bluesky's 2FA sign in email.
18
+
- [ ] generate a 2FA code
19
+
- [ ] createSession gatekeeping (It does stop logins, just eh, doesn't actually send a real code or check it yet)
20
+
- [ ] oauth endpoint gatekeeping
21
+
22
+
## Captcha on Create Account
23
+
24
+
Future feature?
25
+
26
+
# Setup
27
+
28
+
Nothing here yet! If you are brave enough to try before full release, let me know and I'll help you set it up.
29
+
But I want to run it locally on my own PDS first to test run it a bit.
30
+
31
+
Example Caddyfile (mostly so I don't lose it for now. Will have a better one in the future)
32
+
33
+
```caddyfile
34
+
http://localhost {
35
+
36
+
@gatekeeper {
37
+
path /xrpc/com.atproto.server.getSession
38
+
path /xrpc/com.atproto.server.updateEmail
39
+
path /xrpc/com.atproto.server.createSession
40
+
}
41
+
42
+
handle @gatekeeper {
43
+
reverse_proxy http://localhost:8080
44
+
}
45
+
46
+
reverse_proxy /* http://localhost:3000
47
+
}
48
+
49
+
```
+5
build.rs
+5
build.rs
+159
email_templates/two_factor_code.hbs
+159
email_templates/two_factor_code.hbs
···
1
+
<html dir="ltr" lang="en">
2
+
3
+
<head>
4
+
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
5
+
<meta name="x-apple-disable-message-reformatting"/>
6
+
<title>Sign in to Bluesky</title>
7
+
<meta
8
+
name="description"
9
+
content="We received a sign in request for your account."
10
+
/>
11
+
</head>
12
+
<div
13
+
style="display:none;overflow:hidden;line-height:1px;opacity:0;max-height:0;max-width:0"
14
+
>We received a sign-in request for the account @{{handle}}. Use the code below to sign in
15
+
<div
16
+
>
17
+
18
+
</div>
19
+
</div>
20
+
21
+
<body
22
+
style="padding:12px;padding-bottom:40px;background-color:hsl(211, 20%, 95.3%)"
23
+
>
24
+
<table
25
+
align="center"
26
+
width="100%"
27
+
border="0"
28
+
cellPadding="0"
29
+
cellSpacing="0"
30
+
role="presentation"
31
+
style="max-width:37.5em"
32
+
>
33
+
<tbody>
34
+
<tr style="width:100%">
35
+
<td>
36
+
<table
37
+
align="center"
38
+
width="100%"
39
+
border="0"
40
+
cellPadding="0"
41
+
cellSpacing="0"
42
+
role="presentation"
43
+
style="padding-top:24px;padding-bottom:24px"
44
+
>
45
+
<tbody>
46
+
<tr>
47
+
<td><img
48
+
alt="Bluesky"
49
+
src="https://bsky.social/about/images/email/email_logo_default.png"
50
+
style="display:block;outline:none;border:none;text-decoration:none;width:110px;margin:0 auto"
51
+
/></td>
52
+
</tr>
53
+
</tbody>
54
+
</table>
55
+
<table
56
+
align="center"
57
+
width="100%"
58
+
border="0"
59
+
cellPadding="0"
60
+
cellSpacing="0"
61
+
role="presentation"
62
+
style="padding:24px;padding-bottom:16px;border-radius:12px;background-color:#FFFFFF"
63
+
>
64
+
<tbody>
65
+
<tr>
66
+
<td>
67
+
<h1
68
+
style="font-size:26px;letter-spacing:0.25px;color:#000000;font-family:-apple-system, BlinkMacSystemFont, 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;margin:0px 0px;line-height:1.0"
69
+
>Sign in to Bluesky</h1>
70
+
<p
71
+
style="font-size:16px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211, 24%, 34.2%);font-family:-apple-system, BlinkMacSystemFont, 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;padding-top:12px;padding-bottom:12px"
72
+
>We received a sign-in request for the account @{{handle}}. Use the code below to sign in.</p>
73
+
<code
74
+
style="display:block;padding:16px;border-radius:8px;border-width:1px;border-style:solid;background-color:hsl(211, 20%, 95.3%);border-color:hsl(211, 20%, 85.89999999999999%);font-size:14px;letter-spacing:0.25px;font-family:monospace;text-transform:uppercase"
75
+
>{{token}}</code>
76
+
<p style="font-size:14px;line-height:1.4;margin:0px 0px;letter-spacing:0.25px;color:hsl(211,20%,53%);font-family:-apple-system,BlinkMacSystemFont,'Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;padding-top:12px">
77
+
If this wasn't you, we recommend taking steps to
78
+
protect your account by
79
+
<a href="https://bsky.app/settings"
80
+
style="color:hsl(211,20%,53%);text-decoration:none;text-decoration-line:underline;font-family:-apple-system,BlinkMacSystemFont,'Roboto','Oxygen','Ubuntu','Cantarell','Fira Sans','Droid Sans','Helvetica Neue',sans-serif;margin:0px 0px;line-height:1.0;font-size:14px;letter-spacing:0.25px"
81
+
target="_blank"
82
+
data-saferedirecturl="https://bsky.app/settings">changing
83
+
your password.</a></p>
84
+
<table
85
+
align="center"
86
+
width="100%"
87
+
border="0"
88
+
cellPadding="0"
89
+
cellSpacing="0"
90
+
role="presentation"
91
+
style="padding-top:24px"
92
+
>
93
+
<tbody>
94
+
<tr>
95
+
<td>
96
+
<hr
97
+
style="width:100%;border:none;border-top:1px solid #eaeaea;margin:0"
98
+
/>
99
+
<table
100
+
align="center"
101
+
width="100%"
102
+
border="0"
103
+
cellPadding="0"
104
+
cellSpacing="0"
105
+
role="presentation"
106
+
style="padding-top:16px;vertical-align:middle"
107
+
>
108
+
<tbody style="width:100%">
109
+
<tr style="width:100%">
110
+
<td data-id="__react-email-column">
111
+
<p
112
+
style="font-size:14px;line-height:1.4;margin:0px 0px;color:hsl(211, 20%, 53%);font-family:-apple-system, BlinkMacSystemFont, 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;letter-spacing:0.25px"
113
+
><a
114
+
href="https://bsky.app"
115
+
style="color:hsl(211, 20%, 53%);text-decoration:none;text-decoration-line:underline;font-family:-apple-system, BlinkMacSystemFont, 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue', sans-serif;margin:0px 0px;line-height:1.0;font-size:14px;letter-spacing:0.25px"
116
+
target="_blank"
117
+
>Bluesky</a>, the social internet</p>
118
+
</td>
119
+
<td
120
+
data-id="__react-email-column"
121
+
style="width:24px"
122
+
><img
123
+
alt="🦋"
124
+
src="https://bsky.social/about/images/email/email_mark_dark.png"
125
+
style="display:block;outline:none;border:none;text-decoration:none;width:24px"
126
+
/></td>
127
+
</tr>
128
+
</tbody>
129
+
</table>
130
+
</td>
131
+
</tr>
132
+
</tbody>
133
+
</table>
134
+
</td>
135
+
</tr>
136
+
</tbody>
137
+
</table>
138
+
<table
139
+
align="center"
140
+
width="100%"
141
+
border="0"
142
+
cellPadding="0"
143
+
cellSpacing="0"
144
+
role="presentation"
145
+
style="height:500px"
146
+
>
147
+
<tbody>
148
+
<tr>
149
+
<td></td>
150
+
</tr>
151
+
</tbody>
152
+
</table>
153
+
</td>
154
+
</tr>
155
+
</tbody>
156
+
</table>
157
+
</body>
158
+
159
+
</html>
images/gate.jpg
images/gate.jpg
This is a binary file and will not be displayed.
+6
migrations/20250814232704_two_factor_accounts.sql
+6
migrations/20250814232704_two_factor_accounts.sql
+3
migrations_bells_and_whistles/.keep
+3
migrations_bells_and_whistles/.keep
+177
-51
src/main.rs
+177
-51
src/main.rs
···
1
+
use crate::xrpc::com_atproto_server::{create_session, get_session, update_email};
2
+
use axum::middleware as ax_middleware;
3
+
mod middleware;
4
+
use axum::body::Body;
5
+
use axum::handler::Handler;
6
+
use axum::http::{Method, header};
7
+
use axum::routing::post;
8
+
use axum::{Router, routing::get};
9
+
use axum_template::engine::Engine;
10
+
use handlebars::Handlebars;
11
+
use hyper_util::client::legacy::connect::HttpConnector;
12
+
use hyper_util::rt::TokioExecutor;
13
+
use lettre::{AsyncSmtpTransport, Tokio1Executor};
14
+
use rust_embed::RustEmbed;
15
+
use sqlx::sqlite::{SqliteConnectOptions, SqliteJournalMode};
16
+
use sqlx::{SqlitePool, sqlite::SqlitePoolOptions};
17
+
use std::path::Path;
18
+
use std::time::Duration;
1
19
use std::{env, net::SocketAddr};
2
-
use axum::{extract::State, routing::get, Json, Router};
3
-
// use dotenvy::dotenv;
4
-
use serde::Serialize;
5
-
use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};
6
-
use tracing::{error, info, log};
7
-
use tracing_subscriber::{fmt, prelude::*, EnvFilter};
20
+
use tower_governor::GovernorLayer;
21
+
use tower_governor::governor::GovernorConfigBuilder;
22
+
use tower_http::compression::CompressionLayer;
23
+
use tower_http::cors::{Any, CorsLayer};
24
+
use tracing::{error, log};
25
+
use tracing_subscriber::{EnvFilter, fmt, prelude::*};
8
26
9
27
mod xrpc;
10
28
29
+
type HyperUtilClient = hyper_util::client::legacy::Client<HttpConnector, Body>;
30
+
31
+
#[derive(RustEmbed)]
32
+
#[folder = "email_templates"]
33
+
#[include = "*.hbs"]
34
+
struct EmailTemplates;
35
+
11
36
#[derive(Clone)]
12
37
struct AppState {
13
-
pool: SqlitePool,
38
+
account_pool: SqlitePool,
39
+
pds_gatekeeper_pool: SqlitePool,
40
+
reverse_proxy_client: HyperUtilClient,
41
+
pds_base_url: String,
42
+
mailer: AsyncSmtpTransport<Tokio1Executor>,
43
+
mailer_from: String,
44
+
template_engine: Engine<Handlebars<'static>>,
14
45
}
15
46
16
-
#[derive(Serialize)]
17
-
struct HealthResponse {
18
-
status: &'static str,
19
-
}
47
+
async fn root_handler() -> impl axum::response::IntoResponse {
48
+
let body = r"
20
49
21
-
#[derive(Serialize)]
22
-
struct DbPingResponse {
23
-
db: &'static str,
24
-
value: i64,
50
+
...oO _.--X~~OO~~X--._ ...oOO
51
+
_.-~ / \ II / \ ~-._
52
+
[].-~ \ / \||/ \ / ~-.[] ...o
53
+
...o _ ||/ \ / || \ / \|| _
54
+
(_) |X X || X X| (_)
55
+
_-~-_ ||\ / \ || / \ /|| _-~-_
56
+
||||| || \ / \ /||\ / \ / || |||||
57
+
| |_|| \ / \ / || \ / \ / ||_| |
58
+
| |~|| X X || X X ||~| |
59
+
==============| | || / \ / \ || / \ / \ || | |==============
60
+
______________| | || / \ / \||/ \ / \ || | |______________
61
+
. . | | ||/ \ / || \ / \|| | | . .
62
+
/ | | |X X || X X| | | / /
63
+
/ . | | ||\ / \ || / \ /|| | | . / .
64
+
. / | | || \ / \ /||\ / \ / || | | . .
65
+
. . | | || \ / \ / || \ / \ / || | | .
66
+
/ | | || X X || X X || | | . / . /
67
+
/ . | | || / \ / \ || / \ / \ || | | /
68
+
/ | | || / \ / \||/ \ / \ || | | . /
69
+
. . . | | ||/ \ / /||\ \ / \|| | | /. .
70
+
| |_|X X / II \ X X|_| | . . /
71
+
==============| |~II~~~~~~~~~~~~~~OO~~~~~~~~~~~~~~II~| |==============
72
+
";
73
+
74
+
let intro = "\n\nThis is a PDS gatekeeper\n\nCode: https://tangled.sh/@baileytownsend.dev/pds-gatekeeper\n";
75
+
76
+
let banner = format!(" {}\n{}", body, intro);
77
+
78
+
(
79
+
[(header::CONTENT_TYPE, "text/plain; charset=utf-8")],
80
+
banner,
81
+
)
25
82
}
26
83
27
84
#[tokio::main]
28
85
async fn main() -> Result<(), Box<dyn std::error::Error>> {
29
86
setup_tracing();
30
87
//TODO prod
31
-
// dotenvy::from_path(Path::new("/pds.env"))?;
32
-
// let pds_root = env::var("PDS_DATA_DIRECTORY")?;
33
-
let pds_root = "/home/baileytownsend/Documents/code/docker_compose/pds/pds_data";
88
+
dotenvy::from_path(Path::new("./pds.env"))?;
89
+
let pds_root = env::var("PDS_DATA_DIRECTORY")?;
90
+
// let pds_root = "/home/baileytownsend/Documents/code/docker_compose/pds/pds_data";
34
91
let account_db_url = format!("{}/account.sqlite", pds_root);
35
92
log::info!("accounts_db_url: {}", account_db_url);
36
-
let max_connections: u32 = env::var("DATABASE_MAX_CONNECTIONS")
37
-
.ok()
38
-
.and_then(|s| s.parse().ok())
39
-
.unwrap_or(5);
40
93
41
-
//TODO may need to add journal_mode=WAL ?
42
-
let pool = SqlitePoolOptions::new()
43
-
.max_connections(max_connections)
44
-
.connect(&account_db_url)
94
+
let account_options = SqliteConnectOptions::new()
95
+
.journal_mode(SqliteJournalMode::Wal)
96
+
.filename(account_db_url);
97
+
98
+
let account_pool = SqlitePoolOptions::new()
99
+
.max_connections(5)
100
+
.connect_with(account_options)
45
101
.await?;
46
102
47
-
let state = AppState { pool };
103
+
let bells_db_url = format!("{}/pds_gatekeeper.sqlite", pds_root);
104
+
let options = SqliteConnectOptions::new()
105
+
.journal_mode(SqliteJournalMode::Wal)
106
+
.filename(bells_db_url)
107
+
.create_if_missing(true);
108
+
let pds_gatekeeper_pool = SqlitePoolOptions::new()
109
+
.max_connections(5)
110
+
.connect_with(options)
111
+
.await?;
112
+
113
+
// Run migrations for the bells_and_whistles database
114
+
// Note: the migrations are embedded at compile time from the given directory
115
+
// sqlx
116
+
sqlx::migrate!("./migrations")
117
+
.run(&pds_gatekeeper_pool)
118
+
.await?;
119
+
120
+
let client: HyperUtilClient =
121
+
hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
122
+
.build(HttpConnector::new());
123
+
124
+
//Emailer set up
125
+
let smtp_url =
126
+
env::var("PDS_EMAIL_SMTP_URL").expect("PDS_EMAIL_SMTP_URL is not set in your pds.env file");
127
+
let sent_from = env::var("PDS_EMAIL_FROM_ADDRESS")
128
+
.expect("PDS_EMAIL_FROM_ADDRESS is not set in your pds.env file");
129
+
let mailer: AsyncSmtpTransport<Tokio1Executor> =
130
+
AsyncSmtpTransport::<Tokio1Executor>::from_url(smtp_url.as_str())?.build();
131
+
//Email templates setup
132
+
let mut hbs = Handlebars::new();
133
+
let _ = hbs.register_embed_templates::<EmailTemplates>();
134
+
135
+
let state = AppState {
136
+
account_pool,
137
+
pds_gatekeeper_pool,
138
+
reverse_proxy_client: client,
139
+
//TODO should be env prob
140
+
pds_base_url: "http://localhost:3000".to_string(),
141
+
mailer,
142
+
mailer_from: sent_from,
143
+
template_engine: Engine::from(hbs),
144
+
};
145
+
146
+
// Rate limiting
147
+
//Allows 5 within 60 seconds, and after 60 should drop one off? So hit 5, then goes to 4 after 60 seconds.
148
+
let governor_conf = GovernorConfigBuilder::default()
149
+
.per_second(60)
150
+
.burst_size(5)
151
+
.finish()
152
+
.unwrap();
153
+
let governor_limiter = governor_conf.limiter().clone();
154
+
let interval = Duration::from_secs(60);
155
+
// a separate background task to clean up
156
+
std::thread::spawn(move || {
157
+
loop {
158
+
std::thread::sleep(interval);
159
+
tracing::info!("rate limiting storage size: {}", governor_limiter.len());
160
+
governor_limiter.retain_recent();
161
+
}
162
+
});
163
+
164
+
let cors = CorsLayer::new()
165
+
.allow_origin(Any)
166
+
.allow_methods([Method::GET, Method::OPTIONS, Method::POST])
167
+
.allow_headers(Any);
48
168
49
169
let app = Router::new()
50
-
.route("/health", get(health))
51
-
.route("/db/ping", get(db_ping))
170
+
.route("/", get(root_handler))
171
+
.route(
172
+
"/xrpc/com.atproto.server.getSession",
173
+
get(get_session).layer(ax_middleware::from_fn(middleware::extract_did)),
174
+
)
175
+
.route(
176
+
"/xrpc/com.atproto.server.updateEmail",
177
+
post(update_email).layer(ax_middleware::from_fn(middleware::extract_did)),
178
+
)
179
+
.route(
180
+
"/xrpc/com.atproto.server.createSession",
181
+
post(create_session.layer(GovernorLayer::new(governor_conf))),
182
+
)
183
+
.layer(CompressionLayer::new())
184
+
.layer(cors)
52
185
.with_state(state);
53
186
54
187
let host = env::var("HOST").unwrap_or_else(|_| "127.0.0.1".to_string());
55
-
let port: u16 = env::var("PORT").ok().and_then(|s| s.parse().ok()).unwrap_or(8080);
56
-
let addr: SocketAddr = format!("{host}:{port}").parse().expect("valid socket address");
57
-
58
-
info!(%addr, %account_db_url, "starting server");
188
+
let port: u16 = env::var("PORT")
189
+
.ok()
190
+
.and_then(|s| s.parse().ok())
191
+
.unwrap_or(8080);
192
+
let addr: SocketAddr = format!("{host}:{port}")
193
+
.parse()
194
+
.expect("valid socket address");
59
195
60
196
let listener = tokio::net::TcpListener::bind(addr).await?;
61
197
62
-
let server = axum::serve(listener, app).with_graceful_shutdown(shutdown_signal());
198
+
let server = axum::serve(
199
+
listener,
200
+
app.into_make_service_with_connect_info::<SocketAddr>(),
201
+
)
202
+
.with_graceful_shutdown(shutdown_signal());
63
203
64
204
if let Err(err) = server.await {
65
205
error!(error = %err, "server error");
···
68
208
Ok(())
69
209
}
70
210
71
-
async fn health() -> Json<HealthResponse> {
72
-
Json(HealthResponse { status: "ok" })
73
-
}
74
-
75
-
async fn db_ping(State(state): State<AppState>) -> Result<Json<DbPingResponse>, axum::http::StatusCode> {
76
-
// Run a DB-agnostic ping that doesn't depend on user tables.
77
-
// In SQLite, SELECT 1 returns a single row with value 1.
78
-
let v: i64 = sqlx::query_scalar("SELECT 1")
79
-
.fetch_one(&state.pool)
80
-
.await
81
-
.map_err(|_| axum::http::StatusCode::SERVICE_UNAVAILABLE)?;
82
-
83
-
Ok(Json(DbPingResponse { db: "ok", value: v }))
84
-
}
85
-
86
211
fn setup_tracing() {
87
212
let env_filter = EnvFilter::try_from_default_env().unwrap_or_else(|_| EnvFilter::new("info"));
88
213
tracing_subscriber::registry()
···
101
226
102
227
#[cfg(unix)]
103
228
let terminate = async {
104
-
use tokio::signal::unix::{signal, SignalKind};
229
+
use tokio::signal::unix::{SignalKind, signal};
105
230
106
-
let mut sigterm = signal(SignalKind::terminate()).expect("failed to install signal handler");
231
+
let mut sigterm =
232
+
signal(SignalKind::terminate()).expect("failed to install signal handler");
107
233
sigterm.recv().await;
108
234
};
109
235
+97
src/middleware.rs
+97
src/middleware.rs
···
1
+
use crate::xrpc::helpers::json_error_response;
2
+
use axum::extract::Request;
3
+
use axum::http::{HeaderMap, StatusCode};
4
+
use axum::middleware::Next;
5
+
use axum::response::IntoResponse;
6
+
use jwt_compact::alg::{Hs256, Hs256Key};
7
+
use jwt_compact::{AlgorithmExt, Claims, Token, UntrustedToken, ValidationError};
8
+
use serde::{Deserialize, Serialize};
9
+
use std::env;
10
+
11
+
#[derive(Clone, Debug)]
12
+
pub struct Did(pub Option<String>);
13
+
14
+
#[derive(Serialize, Deserialize)]
15
+
pub struct TokenClaims {
16
+
pub sub: String,
17
+
}
18
+
19
+
pub async fn extract_did(mut req: Request, next: Next) -> impl IntoResponse {
20
+
let token = extract_bearer(req.headers());
21
+
22
+
match token {
23
+
Ok(token) => {
24
+
match token {
25
+
None => {
26
+
return json_error_response(
27
+
StatusCode::BAD_REQUEST,
28
+
"TokenRequired",
29
+
"",
30
+
).unwrap();
31
+
}
32
+
Some(token) => {
33
+
let token = UntrustedToken::new(&token);
34
+
//Doing weird unwraps cause I can't do Result for middleware?
35
+
if token.is_err() {
36
+
return json_error_response(
37
+
StatusCode::BAD_REQUEST,
38
+
"TokenRequired",
39
+
"",
40
+
).unwrap();
41
+
}
42
+
let parsed_token = token.unwrap();
43
+
let claims: Result<Claims<TokenClaims>, ValidationError> =
44
+
parsed_token.deserialize_claims_unchecked();
45
+
if claims.is_err() {
46
+
return json_error_response(
47
+
StatusCode::BAD_REQUEST,
48
+
"TokenRequired",
49
+
"",
50
+
).unwrap();
51
+
}
52
+
53
+
let key = Hs256Key::new(env::var("PDS_JWT_SECRET").unwrap());
54
+
let token: Result<Token<TokenClaims>, ValidationError> =
55
+
Hs256.validator(&key).validate(&parsed_token);
56
+
if token.is_err() {
57
+
return json_error_response(
58
+
StatusCode::BAD_REQUEST,
59
+
"InvalidToken",
60
+
"",
61
+
).unwrap();
62
+
}
63
+
let token = token.unwrap();
64
+
//Not going to worry about expiration since it still goes to the PDS
65
+
66
+
req.extensions_mut()
67
+
.insert(Did(Some(token.claims().custom.sub.clone())));
68
+
next.run(req).await
69
+
}
70
+
}
71
+
}
72
+
Err(_) => {
73
+
return json_error_response(
74
+
StatusCode::BAD_REQUEST,
75
+
"InvalidToken",
76
+
"",
77
+
).unwrap();
78
+
}
79
+
}
80
+
}
81
+
82
+
fn extract_bearer(headers: &HeaderMap) -> Result<Option<String>, String> {
83
+
match headers.get(axum::http::header::AUTHORIZATION) {
84
+
None => Ok(None),
85
+
Some(hv) => match hv.to_str() {
86
+
Err(_) => Err("Authorization header is not valid".into()),
87
+
Ok(s) => {
88
+
// Accept forms like: "Bearer <token>" (case-sensitive for the scheme here)
89
+
let mut parts = s.splitn(2, ' ');
90
+
match (parts.next(), parts.next()) {
91
+
(Some("Bearer"), Some(tok)) if !tok.is_empty() => Ok(Some(tok.to_string())),
92
+
_ => Err("Authorization header must be in format 'Bearer <token>'".into()),
93
+
}
94
+
}
95
+
},
96
+
}
97
+
}
+396
-15
src/xrpc/com_atproto_server.rs
+396
-15
src/xrpc/com_atproto_server.rs
···
1
+
use crate::AppState;
2
+
use crate::middleware::Did;
3
+
use crate::xrpc::helpers::{ProxiedResult, json_error_response, proxy_get_json};
4
+
use axum::body::Body;
1
5
use axum::extract::State;
2
-
use axum::{extract, Json};
3
-
use serde::Deserialize;
4
-
use crate::{AppState, DbPingResponse};
6
+
use axum::http::{HeaderMap, StatusCode};
7
+
use axum::response::{IntoResponse, Response};
8
+
use axum::{Extension, Json, debug_handler, extract, extract::Request};
9
+
use axum_template::TemplateEngine;
10
+
use lettre::message::{MultiPart, SinglePart, header};
11
+
use lettre::{AsyncTransport, Message};
12
+
use serde::{Deserialize, Serialize};
13
+
use serde_json;
14
+
use serde_json::Value;
15
+
use serde_json::value::Map;
16
+
use tracing::log;
5
17
18
+
#[derive(Serialize, Deserialize, Debug, Clone)]
19
+
#[serde(rename_all = "camelCase")]
20
+
enum AccountStatus {
21
+
Takendown,
22
+
Suspended,
23
+
Deactivated,
24
+
}
6
25
7
-
#[derive(Deserialize)]
8
-
struct CreateSessionRequest {
26
+
#[derive(Serialize, Deserialize, Debug, Clone)]
27
+
#[serde(rename_all = "camelCase")]
28
+
struct GetSessionResponse {
29
+
handle: String,
30
+
did: String,
31
+
#[serde(skip_serializing_if = "Option::is_none")]
32
+
email: Option<String>,
33
+
#[serde(skip_serializing_if = "Option::is_none")]
34
+
email_confirmed: Option<bool>,
35
+
#[serde(skip_serializing_if = "Option::is_none")]
36
+
email_auth_factor: Option<bool>,
37
+
#[serde(skip_serializing_if = "Option::is_none")]
38
+
did_doc: Option<String>,
39
+
#[serde(skip_serializing_if = "Option::is_none")]
40
+
active: Option<bool>,
41
+
#[serde(skip_serializing_if = "Option::is_none")]
42
+
status: Option<AccountStatus>,
43
+
}
44
+
45
+
#[derive(Serialize, Deserialize, Debug, Clone)]
46
+
#[serde(rename_all = "camelCase")]
47
+
pub struct UpdateEmailResponse {
48
+
email: String,
49
+
#[serde(skip_serializing_if = "Option::is_none")]
50
+
email_auth_factor: Option<bool>,
51
+
#[serde(skip_serializing_if = "Option::is_none")]
52
+
token: Option<String>,
53
+
}
54
+
55
+
#[allow(dead_code)]
56
+
#[derive(Deserialize, Serialize)]
57
+
#[serde(rename_all = "camelCase")]
58
+
pub struct CreateSessionRequest {
9
59
identifier: String,
10
60
password: String,
11
-
#[serde(rename = "authFactorToken")]
12
61
auth_factor_token: String,
13
-
#[serde(rename = "allowTakendown")]
14
62
allow_takendown: bool,
15
63
}
16
64
17
-
async fn create_session(State(state): State<AppState>, extract::Json(payload): extract::Json<CreateSessionRequest>) -> Result<Json<DbPingResponse>, axum::http::StatusCode> {
18
-
// Run a DB-agnostic ping that doesn't depend on user tables.
19
-
// In SQLite, SELECT 1 returns a single row with value 1.
20
-
let v: i64 = sqlx::query_scalar("SELECT 1")
21
-
.fetch_one(&state.pool)
65
+
pub enum AuthResult {
66
+
WrongIdentityOrPassword,
67
+
TwoFactorRequired,
68
+
TwoFactorFailed,
69
+
/// User does not have 2FA enabled, or passes it
70
+
ProxyThrough,
71
+
}
72
+
73
+
pub enum IdentifierType {
74
+
Email,
75
+
DID,
76
+
Handle,
77
+
}
78
+
79
+
impl IdentifierType {
80
+
fn what_is_it(identifier: String) -> Self {
81
+
if identifier.contains("@") {
82
+
IdentifierType::Email
83
+
} else if identifier.contains("did:") {
84
+
IdentifierType::DID
85
+
} else {
86
+
IdentifierType::Handle
87
+
}
88
+
}
89
+
}
90
+
91
+
async fn verify_password(password: &str, password_scrypt: &str) -> Result<bool, StatusCode> {
92
+
// Expected format: "salt:hash" where hash is hex of scrypt(password, salt, 64 bytes)
93
+
let mut parts = password_scrypt.splitn(2, ':');
94
+
let salt = match parts.next() {
95
+
Some(s) if !s.is_empty() => s,
96
+
_ => return Ok(false),
97
+
};
98
+
let stored_hash_hex = match parts.next() {
99
+
Some(h) if !h.is_empty() => h,
100
+
_ => return Ok(false),
101
+
};
102
+
103
+
//Sets up scrypt to mimic node's scrypt
104
+
let params = match scrypt::Params::new(14, 8, 1, 64) {
105
+
Ok(p) => p,
106
+
Err(_) => return Ok(false),
107
+
};
108
+
let mut derived = [0u8; 64];
109
+
if scrypt::scrypt(password.as_bytes(), salt.as_bytes(), ¶ms, &mut derived).is_err() {
110
+
return Ok(false);
111
+
}
112
+
113
+
let stored_bytes = match hex::decode(stored_hash_hex) {
114
+
Ok(b) => b,
115
+
Err(e) => {
116
+
log::error!("Error decoding stored hash: {}", e);
117
+
return Ok(false);
118
+
}
119
+
};
120
+
121
+
Ok(derived.as_slice() == stored_bytes.as_slice())
122
+
}
123
+
124
+
async fn preauth_check(
125
+
state: &AppState,
126
+
identifier: &str,
127
+
password: &str,
128
+
) -> Result<AuthResult, StatusCode> {
129
+
// Determine identifier type
130
+
let id_type = IdentifierType::what_is_it(identifier.to_string());
131
+
132
+
// Query account DB for did and passwordScrypt based on identifier type
133
+
let account_row: Option<(String, String, String)> = match id_type {
134
+
IdentifierType::Email => sqlx::query_as::<_, (String, String, String)>(
135
+
"SELECT did, passwordScrypt, account.email FROM account WHERE email = ? LIMIT 1",
136
+
)
137
+
.bind(identifier)
138
+
.fetch_optional(&state.account_pool)
139
+
.await
140
+
.map_err(|_| StatusCode::BAD_REQUEST)?,
141
+
IdentifierType::Handle => sqlx::query_as::<_, (String, String, String)>(
142
+
"SELECT account.did, account.passwordScrypt, account.email
143
+
FROM actor
144
+
LEFT JOIN account ON actor.did = account.did
145
+
where actor.handle =? LIMIT 1",
146
+
)
147
+
.bind(identifier)
148
+
.fetch_optional(&state.account_pool)
149
+
.await
150
+
.map_err(|_| StatusCode::BAD_REQUEST)?,
151
+
IdentifierType::DID => sqlx::query_as::<_, (String, String, String)>(
152
+
"SELECT did, passwordScrypt, account.email FROM account WHERE did = ? LIMIT 1",
153
+
)
154
+
.bind(identifier)
155
+
.fetch_optional(&state.account_pool)
156
+
.await
157
+
.map_err(|_| StatusCode::BAD_REQUEST)?,
158
+
};
159
+
160
+
if let Some((did, password_scrypt, email)) = account_row {
161
+
// Check two-factor requirement for this DID in the gatekeeper DB
162
+
let required_opt = sqlx::query_as::<_, (u8,)>(
163
+
"SELECT required FROM two_factor_accounts WHERE did = ? LIMIT 1",
164
+
)
165
+
.bind(&did)
166
+
.fetch_optional(&state.pds_gatekeeper_pool)
167
+
.await
168
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
169
+
170
+
let two_factor_required = match required_opt {
171
+
Some(row) => row.0 != 0,
172
+
None => false,
173
+
};
174
+
175
+
if two_factor_required {
176
+
// Verify password before proceeding to 2FA email step
177
+
let verified = verify_password(password, &password_scrypt).await?;
178
+
if !verified {
179
+
return Ok(AuthResult::WrongIdentityOrPassword);
180
+
}
181
+
let mut email_data = Map::new();
182
+
//TODO these need real values
183
+
let token = "test".to_string();
184
+
let handle = "baileytownsend.dev".to_string();
185
+
email_data.insert("token".to_string(), Value::from(token.clone()));
186
+
email_data.insert("handle".to_string(), Value::from(handle.clone()));
187
+
//TODO bad unwrap
188
+
let email_body = state
189
+
.template_engine
190
+
.render("two_factor_code.hbs", email_data)
191
+
.unwrap();
192
+
193
+
let email = Message::builder()
194
+
//TODO prob get the proper type in the state
195
+
.from(state.mailer_from.parse().unwrap())
196
+
.to(email.parse().unwrap())
197
+
.subject("Sign in to Bluesky")
198
+
.multipart(
199
+
MultiPart::alternative() // This is composed of two parts.
200
+
.singlepart(
201
+
SinglePart::builder()
202
+
.header(header::ContentType::TEXT_PLAIN)
203
+
.body(format!("We received a sign-in request for the account @{}. Use the code: {} to sign in. If this wasn't you, we recommend taking steps to protect your account by changing your password at https://bsky.app/settings.", handle, token)), // Every message should have a plain text fallback.
204
+
)
205
+
.singlepart(
206
+
SinglePart::builder()
207
+
.header(header::ContentType::TEXT_HTML)
208
+
.body(email_body),
209
+
),
210
+
)
211
+
//TODO bad
212
+
.unwrap();
213
+
return match state.mailer.send(email).await {
214
+
Ok(_) => Ok(AuthResult::TwoFactorRequired),
215
+
Err(err) => {
216
+
log::error!("Error sending the 2FA email: {}", err);
217
+
Err(StatusCode::BAD_REQUEST)
218
+
}
219
+
};
220
+
}
221
+
}
222
+
223
+
// No local 2FA requirement (or account not found)
224
+
Ok(AuthResult::ProxyThrough)
225
+
}
226
+
227
+
pub async fn create_session(
228
+
State(state): State<AppState>,
229
+
headers: HeaderMap,
230
+
Json(payload): extract::Json<CreateSessionRequest>,
231
+
) -> Result<Response<Body>, StatusCode> {
232
+
let identifier = payload.identifier.clone();
233
+
let password = payload.password.clone();
234
+
235
+
// Run the shared pre-auth logic to validate and check 2FA requirement
236
+
match preauth_check(&state, &identifier, &password).await? {
237
+
AuthResult::WrongIdentityOrPassword => json_error_response(
238
+
StatusCode::UNAUTHORIZED,
239
+
"AuthenticationRequired",
240
+
"Invalid identifier or password",
241
+
),
242
+
AuthResult::TwoFactorRequired => {
243
+
// Email sending step can be handled here if needed in the future.
244
+
json_error_response(
245
+
StatusCode::UNAUTHORIZED,
246
+
"AuthFactorTokenRequired",
247
+
"A sign in code has been sent to your email address",
248
+
)
249
+
}
250
+
AuthResult::TwoFactorFailed => {
251
+
//Not sure what the errors are for this response is yet
252
+
json_error_response(StatusCode::UNAUTHORIZED, "PLACEHOLDER", "PLACEHOLDER")
253
+
}
254
+
AuthResult::ProxyThrough => {
255
+
//No 2FA or already passed
256
+
let uri = format!(
257
+
"{}{}",
258
+
state.pds_base_url, "/xrpc/com.atproto.server.createSession"
259
+
);
260
+
261
+
let mut req = axum::http::Request::post(uri);
262
+
if let Some(req_headers) = req.headers_mut() {
263
+
req_headers.extend(headers.clone());
264
+
}
265
+
266
+
let payload_bytes =
267
+
serde_json::to_vec(&payload).map_err(|_| StatusCode::BAD_REQUEST)?;
268
+
let req = req
269
+
.body(Body::from(payload_bytes))
270
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
271
+
272
+
let proxied = state
273
+
.reverse_proxy_client
274
+
.request(req)
275
+
.await
276
+
.map_err(|_| StatusCode::BAD_REQUEST)?
277
+
.into_response();
278
+
279
+
Ok(proxied)
280
+
}
281
+
}
282
+
}
283
+
284
+
#[debug_handler]
285
+
pub async fn update_email(
286
+
State(state): State<AppState>,
287
+
Extension(did): Extension<Did>,
288
+
headers: HeaderMap,
289
+
Json(payload): extract::Json<UpdateEmailResponse>,
290
+
) -> Result<Response<Body>, StatusCode> {
291
+
//If email auth is not set at all it is a update email address
292
+
let email_auth_not_set = payload.email_auth_factor.is_none();
293
+
//If email aurth is set it is to either turn on or off 2fa
294
+
let email_auth_update = payload.email_auth_factor.unwrap_or(false);
295
+
296
+
// Email update asked for
297
+
if email_auth_update {
298
+
let email = payload.email.clone();
299
+
let email_confirmed = sqlx::query_as::<_, (String,)>(
300
+
"SELECT did FROM account WHERE emailConfirmedAt IS NOT NULL AND email = ?",
301
+
)
302
+
.bind(&email)
303
+
.fetch_optional(&state.account_pool)
304
+
.await
305
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
306
+
307
+
//Since the email is already confirmed we can enable 2fa
308
+
return match email_confirmed {
309
+
None => Err(StatusCode::BAD_REQUEST),
310
+
Some(did_row) => {
311
+
let _ = sqlx::query(
312
+
"INSERT INTO two_factor_accounts (did, required) VALUES (?, 1) ON CONFLICT(did) DO UPDATE SET required = 1",
313
+
)
314
+
.bind(&did_row.0)
315
+
.execute(&state.pds_gatekeeper_pool)
316
+
.await
317
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
318
+
319
+
Ok(StatusCode::OK.into_response())
320
+
}
321
+
};
322
+
}
323
+
324
+
// User wants auth turned off
325
+
if !email_auth_update && !email_auth_not_set {
326
+
//User wants auth turned off and has a token
327
+
if let Some(token) = &payload.token {
328
+
let token_found = sqlx::query_as::<_, (String,)>(
329
+
"SELECT token FROM email_token WHERE token = ? AND did = ? AND purpose = 'update_email'",
330
+
)
331
+
.bind(token)
332
+
.bind(&did.0)
333
+
.fetch_optional(&state.account_pool)
334
+
.await
335
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
336
+
337
+
if token_found.is_some() {
338
+
let _ = sqlx::query(
339
+
"INSERT INTO two_factor_accounts (did, required) VALUES (?, 0) ON CONFLICT(did) DO UPDATE SET required = 0",
340
+
)
341
+
.bind(&did.0)
342
+
.execute(&state.pds_gatekeeper_pool)
343
+
.await
344
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
345
+
346
+
return Ok(StatusCode::OK.into_response());
347
+
} else {
348
+
return Err(StatusCode::BAD_REQUEST);
349
+
}
350
+
}
351
+
}
352
+
353
+
// Updating the acutal email address
354
+
let uri = format!(
355
+
"{}{}",
356
+
state.pds_base_url, "/xrpc/com.atproto.server.updateEmail"
357
+
);
358
+
let mut req = axum::http::Request::post(uri);
359
+
if let Some(req_headers) = req.headers_mut() {
360
+
req_headers.extend(headers.clone());
361
+
}
362
+
363
+
let payload_bytes = serde_json::to_vec(&payload).map_err(|_| StatusCode::BAD_REQUEST)?;
364
+
let req = req
365
+
.body(Body::from(payload_bytes))
366
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
367
+
368
+
let proxied = state
369
+
.reverse_proxy_client
370
+
.request(req)
22
371
.await
23
-
.map_err(|_| axum::http::StatusCode::SERVICE_UNAVAILABLE)?;
372
+
.map_err(|_| StatusCode::BAD_REQUEST)?
373
+
.into_response();
374
+
375
+
Ok(proxied)
376
+
}
377
+
378
+
pub async fn get_session(
379
+
State(state): State<AppState>,
380
+
req: Request,
381
+
) -> Result<Response<Body>, StatusCode> {
382
+
match proxy_get_json::<GetSessionResponse>(&state, req, "/xrpc/com.atproto.server.getSession")
383
+
.await?
384
+
{
385
+
ProxiedResult::Parsed {
386
+
value: mut session, ..
387
+
} => {
388
+
let did = session.did.clone();
389
+
let required_opt = sqlx::query_as::<_, (u8,)>(
390
+
"SELECT required FROM two_factor_accounts WHERE did = ? LIMIT 1",
391
+
)
392
+
.bind(&did)
393
+
.fetch_optional(&state.pds_gatekeeper_pool)
394
+
.await
395
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
396
+
397
+
let email_auth_factor = match required_opt {
398
+
Some(row) => row.0 != 0,
399
+
None => false,
400
+
};
24
401
25
-
Ok(Json(DbPingResponse { db: "ok", value: v }))
26
-
}
402
+
session.email_auth_factor = Some(email_auth_factor);
403
+
Ok(Json(session).into_response())
404
+
}
405
+
ProxiedResult::Passthrough(resp) => Ok(resp),
406
+
}
407
+
}
+150
src/xrpc/helpers.rs
+150
src/xrpc/helpers.rs
···
1
+
use axum::body::{Body, to_bytes};
2
+
use axum::extract::Request;
3
+
use axum::http::{HeaderMap, Method, StatusCode, Uri};
4
+
use axum::http::header::CONTENT_TYPE;
5
+
use axum::response::{IntoResponse, Response};
6
+
use serde::de::DeserializeOwned;
7
+
use tracing::error;
8
+
9
+
use crate::AppState;
10
+
11
+
/// The result of a proxied call that attempts to parse JSON.
12
+
pub enum ProxiedResult<T> {
13
+
/// Successfully parsed JSON body along with original response headers.
14
+
Parsed { value: T, _headers: HeaderMap },
15
+
/// Could not or should not parse: return the original (or rebuilt) response as-is.
16
+
Passthrough(Response<Body>),
17
+
}
18
+
19
+
/// Proxy the incoming request to the PDS base URL plus the provided path and attempt to parse
20
+
/// the successful response body as JSON into `T`.
21
+
///
22
+
/// Behavior:
23
+
/// - If the proxied response is non-200, returns Passthrough with the original response.
24
+
/// - If the response is 200 but JSON parsing fails, returns Passthrough with the original body and headers.
25
+
/// - If parsing succeeds, returns Parsed { value, headers }.
26
+
pub async fn proxy_get_json<T>(
27
+
state: &AppState,
28
+
mut req: Request,
29
+
path: &str,
30
+
) -> Result<ProxiedResult<T>, StatusCode>
31
+
where
32
+
T: DeserializeOwned,
33
+
{
34
+
let uri = format!("{}{}", state.pds_base_url, path);
35
+
*req.uri_mut() = Uri::try_from(uri).map_err(|_| StatusCode::BAD_REQUEST)?;
36
+
37
+
let result = state
38
+
.reverse_proxy_client
39
+
.request(req)
40
+
.await
41
+
.map_err(|_| StatusCode::BAD_REQUEST)?
42
+
.into_response();
43
+
44
+
if result.status() != StatusCode::OK {
45
+
return Ok(ProxiedResult::Passthrough(result));
46
+
}
47
+
48
+
let response_headers = result.headers().clone();
49
+
let body = result.into_body();
50
+
let body_bytes = to_bytes(body, usize::MAX)
51
+
.await
52
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
53
+
54
+
match serde_json::from_slice::<T>(&body_bytes) {
55
+
Ok(value) => Ok(ProxiedResult::Parsed {
56
+
value,
57
+
_headers: response_headers,
58
+
}),
59
+
Err(err) => {
60
+
error!(%err, "failed to parse proxied JSON response; returning original body");
61
+
let mut builder = Response::builder().status(StatusCode::OK);
62
+
if let Some(headers) = builder.headers_mut() {
63
+
*headers = response_headers;
64
+
}
65
+
let resp = builder
66
+
.body(Body::from(body_bytes))
67
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
68
+
Ok(ProxiedResult::Passthrough(resp))
69
+
}
70
+
}
71
+
}
72
+
73
+
/// Proxy the incoming request as a POST to the PDS base URL plus the provided path and attempt to parse
74
+
/// the successful response body as JSON into `T`.
75
+
///
76
+
/// Behavior mirrors `proxy_get_json`:
77
+
/// - If the proxied response is non-200, returns Passthrough with the original response.
78
+
/// - If the response is 200 but JSON parsing fails, returns Passthrough with the original body and headers.
79
+
/// - If parsing succeeds, returns Parsed { value, headers }.
80
+
pub async fn _proxy_post_json<T>(
81
+
state: &AppState,
82
+
mut req: Request,
83
+
path: &str,
84
+
) -> Result<ProxiedResult<T>, StatusCode>
85
+
where
86
+
T: DeserializeOwned,
87
+
{
88
+
let uri = format!("{}{}", state.pds_base_url, path);
89
+
*req.uri_mut() = Uri::try_from(uri).map_err(|_| StatusCode::BAD_REQUEST)?;
90
+
*req.method_mut() = Method::POST;
91
+
92
+
let result = state
93
+
.reverse_proxy_client
94
+
.request(req)
95
+
.await
96
+
.map_err(|_| StatusCode::BAD_REQUEST)?
97
+
.into_response();
98
+
99
+
if result.status() != StatusCode::OK {
100
+
return Ok(ProxiedResult::Passthrough(result));
101
+
}
102
+
103
+
let response_headers = result.headers().clone();
104
+
let body = result.into_body();
105
+
let body_bytes = to_bytes(body, usize::MAX)
106
+
.await
107
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
108
+
109
+
match serde_json::from_slice::<T>(&body_bytes) {
110
+
Ok(value) => Ok(ProxiedResult::Parsed {
111
+
value,
112
+
_headers: response_headers,
113
+
}),
114
+
Err(err) => {
115
+
error!(%err, "failed to parse proxied JSON response (POST); returning original body");
116
+
let mut builder = Response::builder().status(StatusCode::OK);
117
+
if let Some(headers) = builder.headers_mut() {
118
+
*headers = response_headers;
119
+
}
120
+
let resp = builder
121
+
.body(Body::from(body_bytes))
122
+
.map_err(|_| StatusCode::BAD_REQUEST)?;
123
+
Ok(ProxiedResult::Passthrough(resp))
124
+
}
125
+
}
126
+
}
127
+
128
+
129
+
/// Build a JSON error response with the required Content-Type header
130
+
/// Content-Type: application/json;charset=utf-8
131
+
/// Body shape: { "error": string, "message": string }
132
+
pub fn json_error_response(
133
+
status: StatusCode,
134
+
error: impl Into<String>,
135
+
message: impl Into<String>,
136
+
) -> Result<Response<Body>, StatusCode> {
137
+
let body_str = match serde_json::to_string(&serde_json::json!({
138
+
"error": error.into(),
139
+
"message": message.into(),
140
+
})) {
141
+
Ok(s) => s,
142
+
Err(_) => return Err(StatusCode::BAD_REQUEST),
143
+
};
144
+
145
+
Response::builder()
146
+
.status(status)
147
+
.header(CONTENT_TYPE, "application/json;charset=utf-8")
148
+
.body(Body::from(body_str))
149
+
.map_err(|_| StatusCode::BAD_REQUEST)
150
+
}