+17
.env.example
+17
.env.example
···
···
1
+
SERVER_HOST=127.0.0.1
2
+
SERVER_PORT=3000
3
+
4
+
DATABASE_URL=postgres://postgres:postgres@localhost:5432/pds
5
+
6
+
OBJECT_STORAGE_ENDPOINT=
7
+
OBJECT_STORAGE_REGION=us-east-1
8
+
OBJECT_STORAGE_BUCKET=pds-blobs
9
+
OBJECT_STORAGE_ACCESS_KEY=
10
+
OBJECT_STORAGE_SECRET_KEY=
11
+
12
+
# Set to 'true' for MinIO or other services that need path-style addressing
13
+
OBJECT_STORAGE_FORCE_PATH_STYLE=false
14
+
15
+
JWT_SECRET=your-super-secret-jwt-key-please-change-me
16
+
PDS_HOSTNAME=localhost:3000 # The public-facing hostname of the PDS
17
+
PLC_URL=plc.directory
+5620
Cargo.lock
+5620
Cargo.lock
···
···
1
+
# This file is automatically @generated by Cargo.
2
+
# It is not intended for manual editing.
3
+
version = 4
4
+
5
+
[[package]]
6
+
name = "abnf"
7
+
version = "0.13.0"
8
+
source = "registry+https://github.com/rust-lang/crates.io-index"
9
+
checksum = "087113bd50d9adce24850eed5d0476c7d199d532fce8fab5173650331e09033a"
10
+
dependencies = [
11
+
"abnf-core",
12
+
"nom",
13
+
]
14
+
15
+
[[package]]
16
+
name = "abnf-core"
17
+
version = "0.5.0"
18
+
source = "registry+https://github.com/rust-lang/crates.io-index"
19
+
checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d"
20
+
dependencies = [
21
+
"nom",
22
+
]
23
+
24
+
[[package]]
25
+
name = "adler2"
26
+
version = "2.0.1"
27
+
source = "registry+https://github.com/rust-lang/crates.io-index"
28
+
checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
29
+
30
+
[[package]]
31
+
name = "adler32"
32
+
version = "1.2.0"
33
+
source = "registry+https://github.com/rust-lang/crates.io-index"
34
+
checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234"
35
+
36
+
[[package]]
37
+
name = "aho-corasick"
38
+
version = "1.1.4"
39
+
source = "registry+https://github.com/rust-lang/crates.io-index"
40
+
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
41
+
dependencies = [
42
+
"memchr",
43
+
]
44
+
45
+
[[package]]
46
+
name = "aliasable"
47
+
version = "0.1.3"
48
+
source = "registry+https://github.com/rust-lang/crates.io-index"
49
+
checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
50
+
51
+
[[package]]
52
+
name = "alloc-no-stdlib"
53
+
version = "2.0.4"
54
+
source = "registry+https://github.com/rust-lang/crates.io-index"
55
+
checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3"
56
+
57
+
[[package]]
58
+
name = "alloc-stdlib"
59
+
version = "0.2.2"
60
+
source = "registry+https://github.com/rust-lang/crates.io-index"
61
+
checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece"
62
+
dependencies = [
63
+
"alloc-no-stdlib",
64
+
]
65
+
66
+
[[package]]
67
+
name = "allocator-api2"
68
+
version = "0.2.21"
69
+
source = "registry+https://github.com/rust-lang/crates.io-index"
70
+
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
71
+
72
+
[[package]]
73
+
name = "android_system_properties"
74
+
version = "0.1.5"
75
+
source = "registry+https://github.com/rust-lang/crates.io-index"
76
+
checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
77
+
dependencies = [
78
+
"libc",
79
+
]
80
+
81
+
[[package]]
82
+
name = "anyhow"
83
+
version = "1.0.100"
84
+
source = "registry+https://github.com/rust-lang/crates.io-index"
85
+
checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61"
86
+
87
+
[[package]]
88
+
name = "ascii"
89
+
version = "1.1.0"
90
+
source = "registry+https://github.com/rust-lang/crates.io-index"
91
+
checksum = "d92bec98840b8f03a5ff5413de5293bfcd8bf96467cf5452609f939ec6f5de16"
92
+
93
+
[[package]]
94
+
name = "async-compression"
95
+
version = "0.4.34"
96
+
source = "registry+https://github.com/rust-lang/crates.io-index"
97
+
checksum = "0e86f6d3dc9dc4352edeea6b8e499e13e3f5dc3b964d7ca5fd411415a3498473"
98
+
dependencies = [
99
+
"compression-codecs",
100
+
"compression-core",
101
+
"futures-core",
102
+
"pin-project-lite",
103
+
"tokio",
104
+
]
105
+
106
+
[[package]]
107
+
name = "async-trait"
108
+
version = "0.1.89"
109
+
source = "registry+https://github.com/rust-lang/crates.io-index"
110
+
checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
111
+
dependencies = [
112
+
"proc-macro2",
113
+
"quote",
114
+
"syn 2.0.111",
115
+
]
116
+
117
+
[[package]]
118
+
name = "atoi"
119
+
version = "2.0.0"
120
+
source = "registry+https://github.com/rust-lang/crates.io-index"
121
+
checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
122
+
dependencies = [
123
+
"num-traits",
124
+
]
125
+
126
+
[[package]]
127
+
name = "atomic-waker"
128
+
version = "1.1.2"
129
+
source = "registry+https://github.com/rust-lang/crates.io-index"
130
+
checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0"
131
+
132
+
[[package]]
133
+
name = "autocfg"
134
+
version = "1.5.0"
135
+
source = "registry+https://github.com/rust-lang/crates.io-index"
136
+
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
137
+
138
+
[[package]]
139
+
name = "axum"
140
+
version = "0.8.7"
141
+
source = "registry+https://github.com/rust-lang/crates.io-index"
142
+
checksum = "5b098575ebe77cb6d14fc7f32749631a6e44edbef6b796f89b020e99ba20d425"
143
+
dependencies = [
144
+
"axum-core",
145
+
"bytes",
146
+
"form_urlencoded",
147
+
"futures-util",
148
+
"http",
149
+
"http-body",
150
+
"http-body-util",
151
+
"hyper",
152
+
"hyper-util",
153
+
"itoa",
154
+
"matchit",
155
+
"memchr",
156
+
"mime",
157
+
"percent-encoding",
158
+
"pin-project-lite",
159
+
"serde_core",
160
+
"serde_json",
161
+
"serde_path_to_error",
162
+
"serde_urlencoded",
163
+
"sync_wrapper",
164
+
"tokio",
165
+
"tower",
166
+
"tower-layer",
167
+
"tower-service",
168
+
"tracing",
169
+
]
170
+
171
+
[[package]]
172
+
name = "axum-core"
173
+
version = "0.5.5"
174
+
source = "registry+https://github.com/rust-lang/crates.io-index"
175
+
checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22"
176
+
dependencies = [
177
+
"bytes",
178
+
"futures-core",
179
+
"http",
180
+
"http-body",
181
+
"http-body-util",
182
+
"mime",
183
+
"pin-project-lite",
184
+
"sync_wrapper",
185
+
"tower-layer",
186
+
"tower-service",
187
+
"tracing",
188
+
]
189
+
190
+
[[package]]
191
+
name = "base-x"
192
+
version = "0.2.11"
193
+
source = "registry+https://github.com/rust-lang/crates.io-index"
194
+
checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270"
195
+
196
+
[[package]]
197
+
name = "base16ct"
198
+
version = "0.2.0"
199
+
source = "registry+https://github.com/rust-lang/crates.io-index"
200
+
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
201
+
202
+
[[package]]
203
+
name = "base256emoji"
204
+
version = "1.0.2"
205
+
source = "registry+https://github.com/rust-lang/crates.io-index"
206
+
checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c"
207
+
dependencies = [
208
+
"const-str",
209
+
"match-lookup",
210
+
]
211
+
212
+
[[package]]
213
+
name = "base64"
214
+
version = "0.13.1"
215
+
source = "registry+https://github.com/rust-lang/crates.io-index"
216
+
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
217
+
218
+
[[package]]
219
+
name = "base64"
220
+
version = "0.22.1"
221
+
source = "registry+https://github.com/rust-lang/crates.io-index"
222
+
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
223
+
224
+
[[package]]
225
+
name = "base64ct"
226
+
version = "1.8.0"
227
+
source = "registry+https://github.com/rust-lang/crates.io-index"
228
+
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
229
+
230
+
[[package]]
231
+
name = "bcrypt"
232
+
version = "0.17.1"
233
+
source = "registry+https://github.com/rust-lang/crates.io-index"
234
+
checksum = "abaf6da45c74385272ddf00e1ac074c7d8a6c1a1dda376902bd6a427522a8b2c"
235
+
dependencies = [
236
+
"base64 0.22.1",
237
+
"blowfish",
238
+
"getrandom 0.3.4",
239
+
"subtle",
240
+
"zeroize",
241
+
]
242
+
243
+
[[package]]
244
+
name = "bitflags"
245
+
version = "2.10.0"
246
+
source = "registry+https://github.com/rust-lang/crates.io-index"
247
+
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
248
+
dependencies = [
249
+
"serde_core",
250
+
]
251
+
252
+
[[package]]
253
+
name = "block-buffer"
254
+
version = "0.10.4"
255
+
source = "registry+https://github.com/rust-lang/crates.io-index"
256
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
257
+
dependencies = [
258
+
"generic-array",
259
+
]
260
+
261
+
[[package]]
262
+
name = "blowfish"
263
+
version = "0.9.1"
264
+
source = "registry+https://github.com/rust-lang/crates.io-index"
265
+
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
266
+
dependencies = [
267
+
"byteorder",
268
+
"cipher",
269
+
]
270
+
271
+
[[package]]
272
+
name = "bon"
273
+
version = "3.8.1"
274
+
source = "registry+https://github.com/rust-lang/crates.io-index"
275
+
checksum = "ebeb9aaf9329dff6ceb65c689ca3db33dbf15f324909c60e4e5eef5701ce31b1"
276
+
dependencies = [
277
+
"bon-macros",
278
+
"rustversion",
279
+
]
280
+
281
+
[[package]]
282
+
name = "bon-macros"
283
+
version = "3.8.1"
284
+
source = "registry+https://github.com/rust-lang/crates.io-index"
285
+
checksum = "77e9d642a7e3a318e37c2c9427b5a6a48aa1ad55dcd986f3034ab2239045a645"
286
+
dependencies = [
287
+
"darling",
288
+
"ident_case",
289
+
"prettyplease",
290
+
"proc-macro2",
291
+
"quote",
292
+
"rustversion",
293
+
"syn 2.0.111",
294
+
]
295
+
296
+
[[package]]
297
+
name = "borsh"
298
+
version = "1.6.0"
299
+
source = "registry+https://github.com/rust-lang/crates.io-index"
300
+
checksum = "d1da5ab77c1437701eeff7c88d968729e7766172279eab0676857b3d63af7a6f"
301
+
dependencies = [
302
+
"cfg_aliases",
303
+
]
304
+
305
+
[[package]]
306
+
name = "brotli"
307
+
version = "3.5.0"
308
+
source = "registry+https://github.com/rust-lang/crates.io-index"
309
+
checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391"
310
+
dependencies = [
311
+
"alloc-no-stdlib",
312
+
"alloc-stdlib",
313
+
"brotli-decompressor",
314
+
]
315
+
316
+
[[package]]
317
+
name = "brotli-decompressor"
318
+
version = "2.5.1"
319
+
source = "registry+https://github.com/rust-lang/crates.io-index"
320
+
checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f"
321
+
dependencies = [
322
+
"alloc-no-stdlib",
323
+
"alloc-stdlib",
324
+
]
325
+
326
+
[[package]]
327
+
name = "bspds"
328
+
version = "0.1.0"
329
+
dependencies = [
330
+
"anyhow",
331
+
"axum",
332
+
"bcrypt",
333
+
"bytes",
334
+
"chrono",
335
+
"cid",
336
+
"dotenvy",
337
+
"jacquard",
338
+
"jacquard-axum",
339
+
"jacquard-repo",
340
+
"jsonwebtoken",
341
+
"multihash",
342
+
"reqwest",
343
+
"serde",
344
+
"serde_ipld_dagcbor",
345
+
"serde_json",
346
+
"sha2",
347
+
"sqlx",
348
+
"tokio",
349
+
"tracing",
350
+
"tracing-subscriber",
351
+
"uuid",
352
+
]
353
+
354
+
[[package]]
355
+
name = "btree-range-map"
356
+
version = "0.7.2"
357
+
source = "registry+https://github.com/rust-lang/crates.io-index"
358
+
checksum = "1be5c9672446d3800bcbcaabaeba121fe22f1fb25700c4562b22faf76d377c33"
359
+
dependencies = [
360
+
"btree-slab",
361
+
"cc-traits",
362
+
"range-traits",
363
+
"serde",
364
+
"slab",
365
+
]
366
+
367
+
[[package]]
368
+
name = "btree-slab"
369
+
version = "0.6.1"
370
+
source = "registry+https://github.com/rust-lang/crates.io-index"
371
+
checksum = "7a2b56d3029f075c4fa892428a098425b86cef5c89ae54073137ece416aef13c"
372
+
dependencies = [
373
+
"cc-traits",
374
+
"slab",
375
+
"smallvec",
376
+
]
377
+
378
+
[[package]]
379
+
name = "buf_redux"
380
+
version = "0.8.4"
381
+
source = "registry+https://github.com/rust-lang/crates.io-index"
382
+
checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f"
383
+
dependencies = [
384
+
"memchr",
385
+
"safemem",
386
+
]
387
+
388
+
[[package]]
389
+
name = "bumpalo"
390
+
version = "3.19.0"
391
+
source = "registry+https://github.com/rust-lang/crates.io-index"
392
+
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
393
+
394
+
[[package]]
395
+
name = "bytecount"
396
+
version = "0.6.9"
397
+
source = "registry+https://github.com/rust-lang/crates.io-index"
398
+
checksum = "175812e0be2bccb6abe50bb8d566126198344f707e304f45c648fd8f2cc0365e"
399
+
400
+
[[package]]
401
+
name = "byteorder"
402
+
version = "1.5.0"
403
+
source = "registry+https://github.com/rust-lang/crates.io-index"
404
+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
405
+
406
+
[[package]]
407
+
name = "bytes"
408
+
version = "1.11.0"
409
+
source = "registry+https://github.com/rust-lang/crates.io-index"
410
+
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
411
+
dependencies = [
412
+
"serde",
413
+
]
414
+
415
+
[[package]]
416
+
name = "camino"
417
+
version = "1.2.1"
418
+
source = "registry+https://github.com/rust-lang/crates.io-index"
419
+
checksum = "276a59bf2b2c967788139340c9f0c5b12d7fd6630315c15c217e559de85d2609"
420
+
dependencies = [
421
+
"serde_core",
422
+
]
423
+
424
+
[[package]]
425
+
name = "cargo-platform"
426
+
version = "0.1.9"
427
+
source = "registry+https://github.com/rust-lang/crates.io-index"
428
+
checksum = "e35af189006b9c0f00a064685c727031e3ed2d8020f7ba284d78cc2671bd36ea"
429
+
dependencies = [
430
+
"serde",
431
+
]
432
+
433
+
[[package]]
434
+
name = "cargo_metadata"
435
+
version = "0.14.2"
436
+
source = "registry+https://github.com/rust-lang/crates.io-index"
437
+
checksum = "4acbb09d9ee8e23699b9634375c72795d095bf268439da88562cf9b501f181fa"
438
+
dependencies = [
439
+
"camino",
440
+
"cargo-platform",
441
+
"semver",
442
+
"serde",
443
+
"serde_json",
444
+
]
445
+
446
+
[[package]]
447
+
name = "cbor4ii"
448
+
version = "0.2.14"
449
+
source = "registry+https://github.com/rust-lang/crates.io-index"
450
+
checksum = "b544cf8c89359205f4f990d0e6f3828db42df85b5dac95d09157a250eb0749c4"
451
+
dependencies = [
452
+
"serde",
453
+
]
454
+
455
+
[[package]]
456
+
name = "cc"
457
+
version = "1.2.48"
458
+
source = "registry+https://github.com/rust-lang/crates.io-index"
459
+
checksum = "c481bdbf0ed3b892f6f806287d72acd515b352a4ec27a208489b8c1bc839633a"
460
+
dependencies = [
461
+
"find-msvc-tools",
462
+
"shlex",
463
+
]
464
+
465
+
[[package]]
466
+
name = "cc-traits"
467
+
version = "2.0.0"
468
+
source = "registry+https://github.com/rust-lang/crates.io-index"
469
+
checksum = "060303ef31ef4a522737e1b1ab68c67916f2a787bb2f4f54f383279adba962b5"
470
+
dependencies = [
471
+
"slab",
472
+
]
473
+
474
+
[[package]]
475
+
name = "cesu8"
476
+
version = "1.1.0"
477
+
source = "registry+https://github.com/rust-lang/crates.io-index"
478
+
checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c"
479
+
480
+
[[package]]
481
+
name = "cfg-if"
482
+
version = "1.0.4"
483
+
source = "registry+https://github.com/rust-lang/crates.io-index"
484
+
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
485
+
486
+
[[package]]
487
+
name = "cfg_aliases"
488
+
version = "0.2.1"
489
+
source = "registry+https://github.com/rust-lang/crates.io-index"
490
+
checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
491
+
492
+
[[package]]
493
+
name = "chrono"
494
+
version = "0.4.42"
495
+
source = "registry+https://github.com/rust-lang/crates.io-index"
496
+
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
497
+
dependencies = [
498
+
"iana-time-zone",
499
+
"js-sys",
500
+
"num-traits",
501
+
"serde",
502
+
"wasm-bindgen",
503
+
"windows-link 0.2.1",
504
+
]
505
+
506
+
[[package]]
507
+
name = "chunked_transfer"
508
+
version = "1.5.0"
509
+
source = "registry+https://github.com/rust-lang/crates.io-index"
510
+
checksum = "6e4de3bc4ea267985becf712dc6d9eed8b04c953b3fcfb339ebc87acd9804901"
511
+
512
+
[[package]]
513
+
name = "ciborium"
514
+
version = "0.2.2"
515
+
source = "registry+https://github.com/rust-lang/crates.io-index"
516
+
checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
517
+
dependencies = [
518
+
"ciborium-io",
519
+
"ciborium-ll",
520
+
"serde",
521
+
]
522
+
523
+
[[package]]
524
+
name = "ciborium-io"
525
+
version = "0.2.2"
526
+
source = "registry+https://github.com/rust-lang/crates.io-index"
527
+
checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
528
+
529
+
[[package]]
530
+
name = "ciborium-ll"
531
+
version = "0.2.2"
532
+
source = "registry+https://github.com/rust-lang/crates.io-index"
533
+
checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
534
+
dependencies = [
535
+
"ciborium-io",
536
+
"half",
537
+
]
538
+
539
+
[[package]]
540
+
name = "cid"
541
+
version = "0.11.1"
542
+
source = "registry+https://github.com/rust-lang/crates.io-index"
543
+
checksum = "3147d8272e8fa0ccd29ce51194dd98f79ddfb8191ba9e3409884e751798acf3a"
544
+
dependencies = [
545
+
"core2",
546
+
"multibase",
547
+
"multihash",
548
+
"serde",
549
+
"serde_bytes",
550
+
"unsigned-varint 0.8.0",
551
+
]
552
+
553
+
[[package]]
554
+
name = "cipher"
555
+
version = "0.4.4"
556
+
source = "registry+https://github.com/rust-lang/crates.io-index"
557
+
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
558
+
dependencies = [
559
+
"crypto-common",
560
+
"inout",
561
+
]
562
+
563
+
[[package]]
564
+
name = "combine"
565
+
version = "4.6.7"
566
+
source = "registry+https://github.com/rust-lang/crates.io-index"
567
+
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
568
+
dependencies = [
569
+
"bytes",
570
+
"memchr",
571
+
]
572
+
573
+
[[package]]
574
+
name = "compression-codecs"
575
+
version = "0.4.33"
576
+
source = "registry+https://github.com/rust-lang/crates.io-index"
577
+
checksum = "302266479cb963552d11bd042013a58ef1adc56768016c8b82b4199488f2d4ad"
578
+
dependencies = [
579
+
"compression-core",
580
+
"flate2",
581
+
"memchr",
582
+
]
583
+
584
+
[[package]]
585
+
name = "compression-core"
586
+
version = "0.4.31"
587
+
source = "registry+https://github.com/rust-lang/crates.io-index"
588
+
checksum = "75984efb6ed102a0d42db99afb6c1948f0380d1d91808d5529916e6c08b49d8d"
589
+
590
+
[[package]]
591
+
name = "concurrent-queue"
592
+
version = "2.5.0"
593
+
source = "registry+https://github.com/rust-lang/crates.io-index"
594
+
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
595
+
dependencies = [
596
+
"crossbeam-utils",
597
+
]
598
+
599
+
[[package]]
600
+
name = "const-oid"
601
+
version = "0.9.6"
602
+
source = "registry+https://github.com/rust-lang/crates.io-index"
603
+
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
604
+
605
+
[[package]]
606
+
name = "const-str"
607
+
version = "0.4.3"
608
+
source = "registry+https://github.com/rust-lang/crates.io-index"
609
+
checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3"
610
+
611
+
[[package]]
612
+
name = "cordyceps"
613
+
version = "0.3.4"
614
+
source = "registry+https://github.com/rust-lang/crates.io-index"
615
+
checksum = "688d7fbb8092b8de775ef2536f36c8c31f2bc4006ece2e8d8ad2d17d00ce0a2a"
616
+
dependencies = [
617
+
"loom",
618
+
"tracing",
619
+
]
620
+
621
+
[[package]]
622
+
name = "core-foundation"
623
+
version = "0.9.4"
624
+
source = "registry+https://github.com/rust-lang/crates.io-index"
625
+
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
626
+
dependencies = [
627
+
"core-foundation-sys",
628
+
"libc",
629
+
]
630
+
631
+
[[package]]
632
+
name = "core-foundation"
633
+
version = "0.10.1"
634
+
source = "registry+https://github.com/rust-lang/crates.io-index"
635
+
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
636
+
dependencies = [
637
+
"core-foundation-sys",
638
+
"libc",
639
+
]
640
+
641
+
[[package]]
642
+
name = "core-foundation-sys"
643
+
version = "0.8.7"
644
+
source = "registry+https://github.com/rust-lang/crates.io-index"
645
+
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
646
+
647
+
[[package]]
648
+
name = "core2"
649
+
version = "0.4.0"
650
+
source = "registry+https://github.com/rust-lang/crates.io-index"
651
+
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
652
+
dependencies = [
653
+
"memchr",
654
+
]
655
+
656
+
[[package]]
657
+
name = "cpufeatures"
658
+
version = "0.2.17"
659
+
source = "registry+https://github.com/rust-lang/crates.io-index"
660
+
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
661
+
dependencies = [
662
+
"libc",
663
+
]
664
+
665
+
[[package]]
666
+
name = "crc"
667
+
version = "3.4.0"
668
+
source = "registry+https://github.com/rust-lang/crates.io-index"
669
+
checksum = "5eb8a2a1cd12ab0d987a5d5e825195d372001a4094a0376319d5a0ad71c1ba0d"
670
+
dependencies = [
671
+
"crc-catalog",
672
+
]
673
+
674
+
[[package]]
675
+
name = "crc-catalog"
676
+
version = "2.4.0"
677
+
source = "registry+https://github.com/rust-lang/crates.io-index"
678
+
checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
679
+
680
+
[[package]]
681
+
name = "crc32fast"
682
+
version = "1.5.0"
683
+
source = "registry+https://github.com/rust-lang/crates.io-index"
684
+
checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
685
+
dependencies = [
686
+
"cfg-if",
687
+
]
688
+
689
+
[[package]]
690
+
name = "crossbeam-channel"
691
+
version = "0.5.15"
692
+
source = "registry+https://github.com/rust-lang/crates.io-index"
693
+
checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2"
694
+
dependencies = [
695
+
"crossbeam-utils",
696
+
]
697
+
698
+
[[package]]
699
+
name = "crossbeam-queue"
700
+
version = "0.3.12"
701
+
source = "registry+https://github.com/rust-lang/crates.io-index"
702
+
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
703
+
dependencies = [
704
+
"crossbeam-utils",
705
+
]
706
+
707
+
[[package]]
708
+
name = "crossbeam-utils"
709
+
version = "0.8.21"
710
+
source = "registry+https://github.com/rust-lang/crates.io-index"
711
+
checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
712
+
713
+
[[package]]
714
+
name = "crunchy"
715
+
version = "0.2.4"
716
+
source = "registry+https://github.com/rust-lang/crates.io-index"
717
+
checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
718
+
719
+
[[package]]
720
+
name = "crypto-bigint"
721
+
version = "0.5.5"
722
+
source = "registry+https://github.com/rust-lang/crates.io-index"
723
+
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
724
+
dependencies = [
725
+
"generic-array",
726
+
"rand_core 0.6.4",
727
+
"subtle",
728
+
"zeroize",
729
+
]
730
+
731
+
[[package]]
732
+
name = "crypto-common"
733
+
version = "0.1.6"
734
+
source = "registry+https://github.com/rust-lang/crates.io-index"
735
+
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
736
+
dependencies = [
737
+
"generic-array",
738
+
"typenum",
739
+
]
740
+
741
+
[[package]]
742
+
name = "curve25519-dalek"
743
+
version = "4.1.3"
744
+
source = "registry+https://github.com/rust-lang/crates.io-index"
745
+
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
746
+
dependencies = [
747
+
"cfg-if",
748
+
"cpufeatures",
749
+
"curve25519-dalek-derive",
750
+
"digest",
751
+
"fiat-crypto",
752
+
"rustc_version",
753
+
"subtle",
754
+
"zeroize",
755
+
]
756
+
757
+
[[package]]
758
+
name = "curve25519-dalek-derive"
759
+
version = "0.1.1"
760
+
source = "registry+https://github.com/rust-lang/crates.io-index"
761
+
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
762
+
dependencies = [
763
+
"proc-macro2",
764
+
"quote",
765
+
"syn 2.0.111",
766
+
]
767
+
768
+
[[package]]
769
+
name = "darling"
770
+
version = "0.21.3"
771
+
source = "registry+https://github.com/rust-lang/crates.io-index"
772
+
checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0"
773
+
dependencies = [
774
+
"darling_core",
775
+
"darling_macro",
776
+
]
777
+
778
+
[[package]]
779
+
name = "darling_core"
780
+
version = "0.21.3"
781
+
source = "registry+https://github.com/rust-lang/crates.io-index"
782
+
checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4"
783
+
dependencies = [
784
+
"fnv",
785
+
"ident_case",
786
+
"proc-macro2",
787
+
"quote",
788
+
"strsim",
789
+
"syn 2.0.111",
790
+
]
791
+
792
+
[[package]]
793
+
name = "darling_macro"
794
+
version = "0.21.3"
795
+
source = "registry+https://github.com/rust-lang/crates.io-index"
796
+
checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81"
797
+
dependencies = [
798
+
"darling_core",
799
+
"quote",
800
+
"syn 2.0.111",
801
+
]
802
+
803
+
[[package]]
804
+
name = "dashmap"
805
+
version = "5.5.3"
806
+
source = "registry+https://github.com/rust-lang/crates.io-index"
807
+
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
808
+
dependencies = [
809
+
"cfg-if",
810
+
"hashbrown 0.14.5",
811
+
"lock_api",
812
+
"once_cell",
813
+
"parking_lot_core",
814
+
]
815
+
816
+
[[package]]
817
+
name = "dashmap"
818
+
version = "6.1.0"
819
+
source = "registry+https://github.com/rust-lang/crates.io-index"
820
+
checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf"
821
+
dependencies = [
822
+
"cfg-if",
823
+
"crossbeam-utils",
824
+
"hashbrown 0.14.5",
825
+
"lock_api",
826
+
"once_cell",
827
+
"parking_lot_core",
828
+
]
829
+
830
+
[[package]]
831
+
name = "data-encoding"
832
+
version = "2.9.0"
833
+
source = "registry+https://github.com/rust-lang/crates.io-index"
834
+
checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476"
835
+
836
+
[[package]]
837
+
name = "data-encoding-macro"
838
+
version = "0.1.18"
839
+
source = "registry+https://github.com/rust-lang/crates.io-index"
840
+
checksum = "47ce6c96ea0102f01122a185683611bd5ac8d99e62bc59dd12e6bda344ee673d"
841
+
dependencies = [
842
+
"data-encoding",
843
+
"data-encoding-macro-internal",
844
+
]
845
+
846
+
[[package]]
847
+
name = "data-encoding-macro-internal"
848
+
version = "0.1.16"
849
+
source = "registry+https://github.com/rust-lang/crates.io-index"
850
+
checksum = "8d162beedaa69905488a8da94f5ac3edb4dd4788b732fadb7bd120b2625c1976"
851
+
dependencies = [
852
+
"data-encoding",
853
+
"syn 2.0.111",
854
+
]
855
+
856
+
[[package]]
857
+
name = "deflate"
858
+
version = "1.0.0"
859
+
source = "registry+https://github.com/rust-lang/crates.io-index"
860
+
checksum = "c86f7e25f518f4b81808a2cf1c50996a61f5c2eb394b2393bd87f2a4780a432f"
861
+
dependencies = [
862
+
"adler32",
863
+
"gzip-header",
864
+
]
865
+
866
+
[[package]]
867
+
name = "der"
868
+
version = "0.7.10"
869
+
source = "registry+https://github.com/rust-lang/crates.io-index"
870
+
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
871
+
dependencies = [
872
+
"const-oid",
873
+
"pem-rfc7468",
874
+
"zeroize",
875
+
]
876
+
877
+
[[package]]
878
+
name = "deranged"
879
+
version = "0.5.5"
880
+
source = "registry+https://github.com/rust-lang/crates.io-index"
881
+
checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587"
882
+
dependencies = [
883
+
"powerfmt",
884
+
"serde_core",
885
+
]
886
+
887
+
[[package]]
888
+
name = "derive_more"
889
+
version = "1.0.0"
890
+
source = "registry+https://github.com/rust-lang/crates.io-index"
891
+
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
892
+
dependencies = [
893
+
"derive_more-impl",
894
+
]
895
+
896
+
[[package]]
897
+
name = "derive_more-impl"
898
+
version = "1.0.0"
899
+
source = "registry+https://github.com/rust-lang/crates.io-index"
900
+
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
901
+
dependencies = [
902
+
"proc-macro2",
903
+
"quote",
904
+
"syn 2.0.111",
905
+
"unicode-xid",
906
+
]
907
+
908
+
[[package]]
909
+
name = "diatomic-waker"
910
+
version = "0.2.3"
911
+
source = "registry+https://github.com/rust-lang/crates.io-index"
912
+
checksum = "ab03c107fafeb3ee9f5925686dbb7a73bc76e3932abb0d2b365cb64b169cf04c"
913
+
914
+
[[package]]
915
+
name = "digest"
916
+
version = "0.10.7"
917
+
source = "registry+https://github.com/rust-lang/crates.io-index"
918
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
919
+
dependencies = [
920
+
"block-buffer",
921
+
"const-oid",
922
+
"crypto-common",
923
+
"subtle",
924
+
]
925
+
926
+
[[package]]
927
+
name = "displaydoc"
928
+
version = "0.2.5"
929
+
source = "registry+https://github.com/rust-lang/crates.io-index"
930
+
checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
931
+
dependencies = [
932
+
"proc-macro2",
933
+
"quote",
934
+
"syn 2.0.111",
935
+
]
936
+
937
+
[[package]]
938
+
name = "dotenvy"
939
+
version = "0.15.7"
940
+
source = "registry+https://github.com/rust-lang/crates.io-index"
941
+
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
942
+
943
+
[[package]]
944
+
name = "dyn-clone"
945
+
version = "1.0.20"
946
+
source = "registry+https://github.com/rust-lang/crates.io-index"
947
+
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
948
+
949
+
[[package]]
950
+
name = "ecdsa"
951
+
version = "0.16.9"
952
+
source = "registry+https://github.com/rust-lang/crates.io-index"
953
+
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
954
+
dependencies = [
955
+
"der",
956
+
"digest",
957
+
"elliptic-curve",
958
+
"rfc6979",
959
+
"signature",
960
+
"spki",
961
+
]
962
+
963
+
[[package]]
964
+
name = "ed25519"
965
+
version = "2.2.3"
966
+
source = "registry+https://github.com/rust-lang/crates.io-index"
967
+
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
968
+
dependencies = [
969
+
"pkcs8",
970
+
"signature",
971
+
]
972
+
973
+
[[package]]
974
+
name = "ed25519-dalek"
975
+
version = "2.2.0"
976
+
source = "registry+https://github.com/rust-lang/crates.io-index"
977
+
checksum = "70e796c081cee67dc755e1a36a0a172b897fab85fc3f6bc48307991f64e4eca9"
978
+
dependencies = [
979
+
"curve25519-dalek",
980
+
"ed25519",
981
+
"rand_core 0.6.4",
982
+
"serde",
983
+
"sha2",
984
+
"subtle",
985
+
"zeroize",
986
+
]
987
+
988
+
[[package]]
989
+
name = "either"
990
+
version = "1.15.0"
991
+
source = "registry+https://github.com/rust-lang/crates.io-index"
992
+
checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
993
+
dependencies = [
994
+
"serde",
995
+
]
996
+
997
+
[[package]]
998
+
name = "elliptic-curve"
999
+
version = "0.13.8"
1000
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1001
+
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
1002
+
dependencies = [
1003
+
"base16ct",
1004
+
"crypto-bigint",
1005
+
"digest",
1006
+
"ff",
1007
+
"generic-array",
1008
+
"group",
1009
+
"hkdf",
1010
+
"pem-rfc7468",
1011
+
"pkcs8",
1012
+
"rand_core 0.6.4",
1013
+
"sec1",
1014
+
"subtle",
1015
+
"zeroize",
1016
+
]
1017
+
1018
+
[[package]]
1019
+
name = "encoding_rs"
1020
+
version = "0.8.35"
1021
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1022
+
checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
1023
+
dependencies = [
1024
+
"cfg-if",
1025
+
]
1026
+
1027
+
[[package]]
1028
+
name = "enum-as-inner"
1029
+
version = "0.6.1"
1030
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1031
+
checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc"
1032
+
dependencies = [
1033
+
"heck 0.5.0",
1034
+
"proc-macro2",
1035
+
"quote",
1036
+
"syn 2.0.111",
1037
+
]
1038
+
1039
+
[[package]]
1040
+
name = "equivalent"
1041
+
version = "1.0.2"
1042
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1043
+
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
1044
+
1045
+
[[package]]
1046
+
name = "errno"
1047
+
version = "0.3.14"
1048
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1049
+
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
1050
+
dependencies = [
1051
+
"libc",
1052
+
"windows-sys 0.61.2",
1053
+
]
1054
+
1055
+
[[package]]
1056
+
name = "error-chain"
1057
+
version = "0.12.4"
1058
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1059
+
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
1060
+
dependencies = [
1061
+
"version_check",
1062
+
]
1063
+
1064
+
[[package]]
1065
+
name = "etcetera"
1066
+
version = "0.8.0"
1067
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1068
+
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
1069
+
dependencies = [
1070
+
"cfg-if",
1071
+
"home",
1072
+
"windows-sys 0.48.0",
1073
+
]
1074
+
1075
+
[[package]]
1076
+
name = "event-listener"
1077
+
version = "5.4.1"
1078
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1079
+
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
1080
+
dependencies = [
1081
+
"concurrent-queue",
1082
+
"parking",
1083
+
"pin-project-lite",
1084
+
]
1085
+
1086
+
[[package]]
1087
+
name = "fastrand"
1088
+
version = "2.3.0"
1089
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1090
+
checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
1091
+
1092
+
[[package]]
1093
+
name = "ff"
1094
+
version = "0.13.1"
1095
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1096
+
checksum = "c0b50bfb653653f9ca9095b427bed08ab8d75a137839d9ad64eb11810d5b6393"
1097
+
dependencies = [
1098
+
"rand_core 0.6.4",
1099
+
"subtle",
1100
+
]
1101
+
1102
+
[[package]]
1103
+
name = "fiat-crypto"
1104
+
version = "0.2.9"
1105
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1106
+
checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d"
1107
+
1108
+
[[package]]
1109
+
name = "filetime"
1110
+
version = "0.2.26"
1111
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1112
+
checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed"
1113
+
dependencies = [
1114
+
"cfg-if",
1115
+
"libc",
1116
+
"libredox",
1117
+
"windows-sys 0.60.2",
1118
+
]
1119
+
1120
+
[[package]]
1121
+
name = "find-msvc-tools"
1122
+
version = "0.1.5"
1123
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1124
+
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
1125
+
1126
+
[[package]]
1127
+
name = "flate2"
1128
+
version = "1.1.5"
1129
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1130
+
checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb"
1131
+
dependencies = [
1132
+
"crc32fast",
1133
+
"miniz_oxide",
1134
+
]
1135
+
1136
+
[[package]]
1137
+
name = "flume"
1138
+
version = "0.11.1"
1139
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1140
+
checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
1141
+
dependencies = [
1142
+
"futures-core",
1143
+
"futures-sink",
1144
+
"spin 0.9.8",
1145
+
]
1146
+
1147
+
[[package]]
1148
+
name = "fnv"
1149
+
version = "1.0.7"
1150
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1151
+
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
1152
+
1153
+
[[package]]
1154
+
name = "foldhash"
1155
+
version = "0.1.5"
1156
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1157
+
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
1158
+
1159
+
[[package]]
1160
+
name = "foreign-types"
1161
+
version = "0.3.2"
1162
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1163
+
checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1"
1164
+
dependencies = [
1165
+
"foreign-types-shared",
1166
+
]
1167
+
1168
+
[[package]]
1169
+
name = "foreign-types-shared"
1170
+
version = "0.1.1"
1171
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1172
+
checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b"
1173
+
1174
+
[[package]]
1175
+
name = "form_urlencoded"
1176
+
version = "1.2.2"
1177
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1178
+
checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
1179
+
dependencies = [
1180
+
"percent-encoding",
1181
+
]
1182
+
1183
+
[[package]]
1184
+
name = "futf"
1185
+
version = "0.1.5"
1186
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1187
+
checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843"
1188
+
dependencies = [
1189
+
"mac",
1190
+
"new_debug_unreachable",
1191
+
]
1192
+
1193
+
[[package]]
1194
+
name = "futures"
1195
+
version = "0.3.31"
1196
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1197
+
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
1198
+
dependencies = [
1199
+
"futures-channel",
1200
+
"futures-core",
1201
+
"futures-executor",
1202
+
"futures-io",
1203
+
"futures-sink",
1204
+
"futures-task",
1205
+
"futures-util",
1206
+
]
1207
+
1208
+
[[package]]
1209
+
name = "futures-buffered"
1210
+
version = "0.2.12"
1211
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1212
+
checksum = "a8e0e1f38ec07ba4abbde21eed377082f17ccb988be9d988a5adbf4bafc118fd"
1213
+
dependencies = [
1214
+
"cordyceps",
1215
+
"diatomic-waker",
1216
+
"futures-core",
1217
+
"pin-project-lite",
1218
+
"spin 0.10.0",
1219
+
]
1220
+
1221
+
[[package]]
1222
+
name = "futures-channel"
1223
+
version = "0.3.31"
1224
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1225
+
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
1226
+
dependencies = [
1227
+
"futures-core",
1228
+
"futures-sink",
1229
+
]
1230
+
1231
+
[[package]]
1232
+
name = "futures-core"
1233
+
version = "0.3.31"
1234
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1235
+
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
1236
+
1237
+
[[package]]
1238
+
name = "futures-executor"
1239
+
version = "0.3.31"
1240
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1241
+
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
1242
+
dependencies = [
1243
+
"futures-core",
1244
+
"futures-task",
1245
+
"futures-util",
1246
+
]
1247
+
1248
+
[[package]]
1249
+
name = "futures-intrusive"
1250
+
version = "0.5.0"
1251
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1252
+
checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
1253
+
dependencies = [
1254
+
"futures-core",
1255
+
"lock_api",
1256
+
"parking_lot",
1257
+
]
1258
+
1259
+
[[package]]
1260
+
name = "futures-io"
1261
+
version = "0.3.31"
1262
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1263
+
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
1264
+
1265
+
[[package]]
1266
+
name = "futures-lite"
1267
+
version = "2.6.1"
1268
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1269
+
checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad"
1270
+
dependencies = [
1271
+
"fastrand",
1272
+
"futures-core",
1273
+
"futures-io",
1274
+
"parking",
1275
+
"pin-project-lite",
1276
+
]
1277
+
1278
+
[[package]]
1279
+
name = "futures-macro"
1280
+
version = "0.3.31"
1281
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1282
+
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
1283
+
dependencies = [
1284
+
"proc-macro2",
1285
+
"quote",
1286
+
"syn 2.0.111",
1287
+
]
1288
+
1289
+
[[package]]
1290
+
name = "futures-sink"
1291
+
version = "0.3.31"
1292
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1293
+
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
1294
+
1295
+
[[package]]
1296
+
name = "futures-task"
1297
+
version = "0.3.31"
1298
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1299
+
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
1300
+
1301
+
[[package]]
1302
+
name = "futures-util"
1303
+
version = "0.3.31"
1304
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1305
+
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
1306
+
dependencies = [
1307
+
"futures-channel",
1308
+
"futures-core",
1309
+
"futures-io",
1310
+
"futures-macro",
1311
+
"futures-sink",
1312
+
"futures-task",
1313
+
"memchr",
1314
+
"pin-project-lite",
1315
+
"pin-utils",
1316
+
"slab",
1317
+
]
1318
+
1319
+
[[package]]
1320
+
name = "generator"
1321
+
version = "0.8.7"
1322
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1323
+
checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2"
1324
+
dependencies = [
1325
+
"cc",
1326
+
"cfg-if",
1327
+
"libc",
1328
+
"log",
1329
+
"rustversion",
1330
+
"windows",
1331
+
]
1332
+
1333
+
[[package]]
1334
+
name = "generic-array"
1335
+
version = "0.14.9"
1336
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1337
+
checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2"
1338
+
dependencies = [
1339
+
"typenum",
1340
+
"version_check",
1341
+
"zeroize",
1342
+
]
1343
+
1344
+
[[package]]
1345
+
name = "getrandom"
1346
+
version = "0.2.16"
1347
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1348
+
checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
1349
+
dependencies = [
1350
+
"cfg-if",
1351
+
"js-sys",
1352
+
"libc",
1353
+
"wasi",
1354
+
"wasm-bindgen",
1355
+
]
1356
+
1357
+
[[package]]
1358
+
name = "getrandom"
1359
+
version = "0.3.4"
1360
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1361
+
checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd"
1362
+
dependencies = [
1363
+
"cfg-if",
1364
+
"js-sys",
1365
+
"libc",
1366
+
"r-efi",
1367
+
"wasip2",
1368
+
"wasm-bindgen",
1369
+
]
1370
+
1371
+
[[package]]
1372
+
name = "glob"
1373
+
version = "0.3.3"
1374
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1375
+
checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280"
1376
+
1377
+
[[package]]
1378
+
name = "gloo-storage"
1379
+
version = "0.3.0"
1380
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1381
+
checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a"
1382
+
dependencies = [
1383
+
"gloo-utils",
1384
+
"js-sys",
1385
+
"serde",
1386
+
"serde_json",
1387
+
"thiserror 1.0.69",
1388
+
"wasm-bindgen",
1389
+
"web-sys",
1390
+
]
1391
+
1392
+
[[package]]
1393
+
name = "gloo-utils"
1394
+
version = "0.2.0"
1395
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1396
+
checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa"
1397
+
dependencies = [
1398
+
"js-sys",
1399
+
"serde",
1400
+
"serde_json",
1401
+
"wasm-bindgen",
1402
+
"web-sys",
1403
+
]
1404
+
1405
+
[[package]]
1406
+
name = "group"
1407
+
version = "0.13.0"
1408
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1409
+
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
1410
+
dependencies = [
1411
+
"ff",
1412
+
"rand_core 0.6.4",
1413
+
"subtle",
1414
+
]
1415
+
1416
+
[[package]]
1417
+
name = "gzip-header"
1418
+
version = "1.0.0"
1419
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1420
+
checksum = "95cc527b92e6029a62960ad99aa8a6660faa4555fe5f731aab13aa6a921795a2"
1421
+
dependencies = [
1422
+
"crc32fast",
1423
+
]
1424
+
1425
+
[[package]]
1426
+
name = "h2"
1427
+
version = "0.4.12"
1428
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1429
+
checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386"
1430
+
dependencies = [
1431
+
"atomic-waker",
1432
+
"bytes",
1433
+
"fnv",
1434
+
"futures-core",
1435
+
"futures-sink",
1436
+
"http",
1437
+
"indexmap 2.12.1",
1438
+
"slab",
1439
+
"tokio",
1440
+
"tokio-util",
1441
+
"tracing",
1442
+
]
1443
+
1444
+
[[package]]
1445
+
name = "half"
1446
+
version = "2.7.1"
1447
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1448
+
checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b"
1449
+
dependencies = [
1450
+
"cfg-if",
1451
+
"crunchy",
1452
+
"zerocopy",
1453
+
]
1454
+
1455
+
[[package]]
1456
+
name = "hashbrown"
1457
+
version = "0.12.3"
1458
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1459
+
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
1460
+
1461
+
[[package]]
1462
+
name = "hashbrown"
1463
+
version = "0.14.5"
1464
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1465
+
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
1466
+
1467
+
[[package]]
1468
+
name = "hashbrown"
1469
+
version = "0.15.5"
1470
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1471
+
checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
1472
+
dependencies = [
1473
+
"allocator-api2",
1474
+
"equivalent",
1475
+
"foldhash",
1476
+
]
1477
+
1478
+
[[package]]
1479
+
name = "hashbrown"
1480
+
version = "0.16.1"
1481
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1482
+
checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100"
1483
+
1484
+
[[package]]
1485
+
name = "hashlink"
1486
+
version = "0.10.0"
1487
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1488
+
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
1489
+
dependencies = [
1490
+
"hashbrown 0.15.5",
1491
+
]
1492
+
1493
+
[[package]]
1494
+
name = "heck"
1495
+
version = "0.4.1"
1496
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1497
+
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
1498
+
1499
+
[[package]]
1500
+
name = "heck"
1501
+
version = "0.5.0"
1502
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1503
+
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
1504
+
1505
+
[[package]]
1506
+
name = "hermit-abi"
1507
+
version = "0.5.2"
1508
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1509
+
checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
1510
+
1511
+
[[package]]
1512
+
name = "hex"
1513
+
version = "0.4.3"
1514
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1515
+
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
1516
+
1517
+
[[package]]
1518
+
name = "hex_fmt"
1519
+
version = "0.3.0"
1520
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1521
+
checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f"
1522
+
1523
+
[[package]]
1524
+
name = "hickory-proto"
1525
+
version = "0.24.4"
1526
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1527
+
checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248"
1528
+
dependencies = [
1529
+
"async-trait",
1530
+
"cfg-if",
1531
+
"data-encoding",
1532
+
"enum-as-inner",
1533
+
"futures-channel",
1534
+
"futures-io",
1535
+
"futures-util",
1536
+
"idna",
1537
+
"ipnet",
1538
+
"once_cell",
1539
+
"rand 0.8.5",
1540
+
"thiserror 1.0.69",
1541
+
"tinyvec",
1542
+
"tokio",
1543
+
"tracing",
1544
+
"url",
1545
+
]
1546
+
1547
+
[[package]]
1548
+
name = "hickory-resolver"
1549
+
version = "0.24.4"
1550
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1551
+
checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e"
1552
+
dependencies = [
1553
+
"cfg-if",
1554
+
"futures-util",
1555
+
"hickory-proto",
1556
+
"ipconfig",
1557
+
"lru-cache",
1558
+
"once_cell",
1559
+
"parking_lot",
1560
+
"rand 0.8.5",
1561
+
"resolv-conf",
1562
+
"smallvec",
1563
+
"thiserror 1.0.69",
1564
+
"tokio",
1565
+
"tracing",
1566
+
]
1567
+
1568
+
[[package]]
1569
+
name = "hkdf"
1570
+
version = "0.12.4"
1571
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1572
+
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
1573
+
dependencies = [
1574
+
"hmac",
1575
+
]
1576
+
1577
+
[[package]]
1578
+
name = "hmac"
1579
+
version = "0.12.1"
1580
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1581
+
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
1582
+
dependencies = [
1583
+
"digest",
1584
+
]
1585
+
1586
+
[[package]]
1587
+
name = "home"
1588
+
version = "0.5.12"
1589
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1590
+
checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d"
1591
+
dependencies = [
1592
+
"windows-sys 0.61.2",
1593
+
]
1594
+
1595
+
[[package]]
1596
+
name = "html5ever"
1597
+
version = "0.27.0"
1598
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1599
+
checksum = "c13771afe0e6e846f1e67d038d4cb29998a6779f93c809212e4e9c32efd244d4"
1600
+
dependencies = [
1601
+
"log",
1602
+
"mac",
1603
+
"markup5ever",
1604
+
"proc-macro2",
1605
+
"quote",
1606
+
"syn 2.0.111",
1607
+
]
1608
+
1609
+
[[package]]
1610
+
name = "http"
1611
+
version = "1.4.0"
1612
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1613
+
checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a"
1614
+
dependencies = [
1615
+
"bytes",
1616
+
"itoa",
1617
+
]
1618
+
1619
+
[[package]]
1620
+
name = "http-body"
1621
+
version = "1.0.1"
1622
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1623
+
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
1624
+
dependencies = [
1625
+
"bytes",
1626
+
"http",
1627
+
]
1628
+
1629
+
[[package]]
1630
+
name = "http-body-util"
1631
+
version = "0.1.3"
1632
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1633
+
checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
1634
+
dependencies = [
1635
+
"bytes",
1636
+
"futures-core",
1637
+
"http",
1638
+
"http-body",
1639
+
"pin-project-lite",
1640
+
]
1641
+
1642
+
[[package]]
1643
+
name = "httparse"
1644
+
version = "1.10.1"
1645
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1646
+
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
1647
+
1648
+
[[package]]
1649
+
name = "httpdate"
1650
+
version = "1.0.3"
1651
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1652
+
checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
1653
+
1654
+
[[package]]
1655
+
name = "hyper"
1656
+
version = "1.8.1"
1657
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1658
+
checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11"
1659
+
dependencies = [
1660
+
"atomic-waker",
1661
+
"bytes",
1662
+
"futures-channel",
1663
+
"futures-core",
1664
+
"h2",
1665
+
"http",
1666
+
"http-body",
1667
+
"httparse",
1668
+
"httpdate",
1669
+
"itoa",
1670
+
"pin-project-lite",
1671
+
"pin-utils",
1672
+
"smallvec",
1673
+
"tokio",
1674
+
"want",
1675
+
]
1676
+
1677
+
[[package]]
1678
+
name = "hyper-rustls"
1679
+
version = "0.27.7"
1680
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1681
+
checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
1682
+
dependencies = [
1683
+
"http",
1684
+
"hyper",
1685
+
"hyper-util",
1686
+
"rustls",
1687
+
"rustls-pki-types",
1688
+
"tokio",
1689
+
"tokio-rustls",
1690
+
"tower-service",
1691
+
"webpki-roots 1.0.4",
1692
+
]
1693
+
1694
+
[[package]]
1695
+
name = "hyper-tls"
1696
+
version = "0.6.0"
1697
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1698
+
checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0"
1699
+
dependencies = [
1700
+
"bytes",
1701
+
"http-body-util",
1702
+
"hyper",
1703
+
"hyper-util",
1704
+
"native-tls",
1705
+
"tokio",
1706
+
"tokio-native-tls",
1707
+
"tower-service",
1708
+
]
1709
+
1710
+
[[package]]
1711
+
name = "hyper-util"
1712
+
version = "0.1.18"
1713
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1714
+
checksum = "52e9a2a24dc5c6821e71a7030e1e14b7b632acac55c40e9d2e082c621261bb56"
1715
+
dependencies = [
1716
+
"base64 0.22.1",
1717
+
"bytes",
1718
+
"futures-channel",
1719
+
"futures-core",
1720
+
"futures-util",
1721
+
"http",
1722
+
"http-body",
1723
+
"hyper",
1724
+
"ipnet",
1725
+
"libc",
1726
+
"percent-encoding",
1727
+
"pin-project-lite",
1728
+
"socket2 0.6.1",
1729
+
"system-configuration",
1730
+
"tokio",
1731
+
"tower-service",
1732
+
"tracing",
1733
+
"windows-registry",
1734
+
]
1735
+
1736
+
[[package]]
1737
+
name = "iana-time-zone"
1738
+
version = "0.1.64"
1739
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1740
+
checksum = "33e57f83510bb73707521ebaffa789ec8caf86f9657cad665b092b581d40e9fb"
1741
+
dependencies = [
1742
+
"android_system_properties",
1743
+
"core-foundation-sys",
1744
+
"iana-time-zone-haiku",
1745
+
"js-sys",
1746
+
"log",
1747
+
"wasm-bindgen",
1748
+
"windows-core 0.62.2",
1749
+
]
1750
+
1751
+
[[package]]
1752
+
name = "iana-time-zone-haiku"
1753
+
version = "0.1.2"
1754
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1755
+
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
1756
+
dependencies = [
1757
+
"cc",
1758
+
]
1759
+
1760
+
[[package]]
1761
+
name = "icu_collections"
1762
+
version = "2.1.1"
1763
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1764
+
checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43"
1765
+
dependencies = [
1766
+
"displaydoc",
1767
+
"potential_utf",
1768
+
"yoke",
1769
+
"zerofrom",
1770
+
"zerovec",
1771
+
]
1772
+
1773
+
[[package]]
1774
+
name = "icu_locale_core"
1775
+
version = "2.1.1"
1776
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1777
+
checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6"
1778
+
dependencies = [
1779
+
"displaydoc",
1780
+
"litemap",
1781
+
"tinystr",
1782
+
"writeable",
1783
+
"zerovec",
1784
+
]
1785
+
1786
+
[[package]]
1787
+
name = "icu_normalizer"
1788
+
version = "2.1.1"
1789
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1790
+
checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599"
1791
+
dependencies = [
1792
+
"icu_collections",
1793
+
"icu_normalizer_data",
1794
+
"icu_properties",
1795
+
"icu_provider",
1796
+
"smallvec",
1797
+
"zerovec",
1798
+
]
1799
+
1800
+
[[package]]
1801
+
name = "icu_normalizer_data"
1802
+
version = "2.1.1"
1803
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1804
+
checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a"
1805
+
1806
+
[[package]]
1807
+
name = "icu_properties"
1808
+
version = "2.1.1"
1809
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1810
+
checksum = "e93fcd3157766c0c8da2f8cff6ce651a31f0810eaa1c51ec363ef790bbb5fb99"
1811
+
dependencies = [
1812
+
"icu_collections",
1813
+
"icu_locale_core",
1814
+
"icu_properties_data",
1815
+
"icu_provider",
1816
+
"zerotrie",
1817
+
"zerovec",
1818
+
]
1819
+
1820
+
[[package]]
1821
+
name = "icu_properties_data"
1822
+
version = "2.1.1"
1823
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1824
+
checksum = "02845b3647bb045f1100ecd6480ff52f34c35f82d9880e029d329c21d1054899"
1825
+
1826
+
[[package]]
1827
+
name = "icu_provider"
1828
+
version = "2.1.1"
1829
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1830
+
checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614"
1831
+
dependencies = [
1832
+
"displaydoc",
1833
+
"icu_locale_core",
1834
+
"writeable",
1835
+
"yoke",
1836
+
"zerofrom",
1837
+
"zerotrie",
1838
+
"zerovec",
1839
+
]
1840
+
1841
+
[[package]]
1842
+
name = "ident_case"
1843
+
version = "1.0.1"
1844
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1845
+
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
1846
+
1847
+
[[package]]
1848
+
name = "idna"
1849
+
version = "1.1.0"
1850
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1851
+
checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
1852
+
dependencies = [
1853
+
"idna_adapter",
1854
+
"smallvec",
1855
+
"utf8_iter",
1856
+
]
1857
+
1858
+
[[package]]
1859
+
name = "idna_adapter"
1860
+
version = "1.2.1"
1861
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1862
+
checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
1863
+
dependencies = [
1864
+
"icu_normalizer",
1865
+
"icu_properties",
1866
+
]
1867
+
1868
+
[[package]]
1869
+
name = "indexmap"
1870
+
version = "1.9.3"
1871
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1872
+
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
1873
+
dependencies = [
1874
+
"autocfg",
1875
+
"hashbrown 0.12.3",
1876
+
"serde",
1877
+
]
1878
+
1879
+
[[package]]
1880
+
name = "indexmap"
1881
+
version = "2.12.1"
1882
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1883
+
checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2"
1884
+
dependencies = [
1885
+
"equivalent",
1886
+
"hashbrown 0.16.1",
1887
+
"serde",
1888
+
"serde_core",
1889
+
]
1890
+
1891
+
[[package]]
1892
+
name = "indoc"
1893
+
version = "2.0.7"
1894
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1895
+
checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
1896
+
dependencies = [
1897
+
"rustversion",
1898
+
]
1899
+
1900
+
[[package]]
1901
+
name = "inout"
1902
+
version = "0.1.4"
1903
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1904
+
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
1905
+
dependencies = [
1906
+
"generic-array",
1907
+
]
1908
+
1909
+
[[package]]
1910
+
name = "inventory"
1911
+
version = "0.3.21"
1912
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1913
+
checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e"
1914
+
dependencies = [
1915
+
"rustversion",
1916
+
]
1917
+
1918
+
[[package]]
1919
+
name = "ipconfig"
1920
+
version = "0.3.2"
1921
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1922
+
checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
1923
+
dependencies = [
1924
+
"socket2 0.5.10",
1925
+
"widestring",
1926
+
"windows-sys 0.48.0",
1927
+
"winreg",
1928
+
]
1929
+
1930
+
[[package]]
1931
+
name = "ipld-core"
1932
+
version = "0.4.2"
1933
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1934
+
checksum = "104718b1cc124d92a6d01ca9c9258a7df311405debb3408c445a36452f9bf8db"
1935
+
dependencies = [
1936
+
"cid",
1937
+
"serde",
1938
+
"serde_bytes",
1939
+
]
1940
+
1941
+
[[package]]
1942
+
name = "ipnet"
1943
+
version = "2.11.0"
1944
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1945
+
checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130"
1946
+
1947
+
[[package]]
1948
+
name = "iri-string"
1949
+
version = "0.7.9"
1950
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1951
+
checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397"
1952
+
dependencies = [
1953
+
"memchr",
1954
+
"serde",
1955
+
]
1956
+
1957
+
[[package]]
1958
+
name = "iroh-car"
1959
+
version = "0.5.1"
1960
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1961
+
checksum = "cb7f8cd4cb9aa083fba8b52e921764252d0b4dcb1cd6d120b809dbfe1106e81a"
1962
+
dependencies = [
1963
+
"anyhow",
1964
+
"cid",
1965
+
"futures",
1966
+
"serde",
1967
+
"serde_ipld_dagcbor",
1968
+
"thiserror 1.0.69",
1969
+
"tokio",
1970
+
"unsigned-varint 0.7.2",
1971
+
]
1972
+
1973
+
[[package]]
1974
+
name = "itoa"
1975
+
version = "1.0.15"
1976
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1977
+
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
1978
+
1979
+
[[package]]
1980
+
name = "jacquard"
1981
+
version = "0.9.3"
1982
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1983
+
checksum = "c19864761c8d69d23201fd19dd021cddf1fb7acbebb6e6b50e2b1776ec982768"
1984
+
dependencies = [
1985
+
"bytes",
1986
+
"getrandom 0.2.16",
1987
+
"gloo-storage",
1988
+
"http",
1989
+
"jacquard-api",
1990
+
"jacquard-common",
1991
+
"jacquard-derive",
1992
+
"jacquard-identity",
1993
+
"jacquard-oauth",
1994
+
"jose-jwk",
1995
+
"miette",
1996
+
"regex",
1997
+
"regex-lite",
1998
+
"reqwest",
1999
+
"serde",
2000
+
"serde_html_form",
2001
+
"serde_json",
2002
+
"smol_str",
2003
+
"thiserror 2.0.17",
2004
+
"tokio",
2005
+
"trait-variant",
2006
+
"url",
2007
+
"webpage",
2008
+
]
2009
+
2010
+
[[package]]
2011
+
name = "jacquard-api"
2012
+
version = "0.9.2"
2013
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2014
+
checksum = "bbbfd6e2b10fa1731f4d4e40c8f791956b0d4f804fb3efef891afec903f20597"
2015
+
dependencies = [
2016
+
"bon",
2017
+
"bytes",
2018
+
"jacquard-common",
2019
+
"jacquard-derive",
2020
+
"jacquard-lexicon",
2021
+
"miette",
2022
+
"rustversion",
2023
+
"serde",
2024
+
"serde_ipld_dagcbor",
2025
+
"thiserror 2.0.17",
2026
+
"unicode-segmentation",
2027
+
]
2028
+
2029
+
[[package]]
2030
+
name = "jacquard-axum"
2031
+
version = "0.9.2"
2032
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2033
+
checksum = "ee1b58111f0a2a08ee18525ac661a0448fdc84d4ecb423d64aaaf88074460380"
2034
+
dependencies = [
2035
+
"axum",
2036
+
"bytes",
2037
+
"jacquard",
2038
+
"jacquard-common",
2039
+
"jacquard-derive",
2040
+
"jacquard-identity",
2041
+
"miette",
2042
+
"multibase",
2043
+
"serde",
2044
+
"serde_html_form",
2045
+
"serde_json",
2046
+
"thiserror 2.0.17",
2047
+
"tokio",
2048
+
"tower-http",
2049
+
"tracing",
2050
+
]
2051
+
2052
+
[[package]]
2053
+
name = "jacquard-common"
2054
+
version = "0.9.2"
2055
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2056
+
checksum = "df86cb117d9f1c2b0251ba67c3f0e3f963fd22abc6cf8de0e02a7fc846c288ca"
2057
+
dependencies = [
2058
+
"base64 0.22.1",
2059
+
"bon",
2060
+
"bytes",
2061
+
"chrono",
2062
+
"cid",
2063
+
"ed25519-dalek",
2064
+
"getrandom 0.2.16",
2065
+
"getrandom 0.3.4",
2066
+
"http",
2067
+
"ipld-core",
2068
+
"k256",
2069
+
"langtag",
2070
+
"miette",
2071
+
"multibase",
2072
+
"multihash",
2073
+
"ouroboros",
2074
+
"p256",
2075
+
"rand 0.9.2",
2076
+
"regex",
2077
+
"regex-lite",
2078
+
"reqwest",
2079
+
"serde",
2080
+
"serde_html_form",
2081
+
"serde_ipld_dagcbor",
2082
+
"serde_json",
2083
+
"signature",
2084
+
"smol_str",
2085
+
"thiserror 2.0.17",
2086
+
"tokio",
2087
+
"tokio-util",
2088
+
"trait-variant",
2089
+
"url",
2090
+
]
2091
+
2092
+
[[package]]
2093
+
name = "jacquard-derive"
2094
+
version = "0.9.2"
2095
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2096
+
checksum = "42ca61a69dc7aa8fb2d7163416514ff7df5d79f2e8b22e269f4610afa85572fe"
2097
+
dependencies = [
2098
+
"heck 0.5.0",
2099
+
"jacquard-lexicon",
2100
+
"proc-macro2",
2101
+
"quote",
2102
+
"syn 2.0.111",
2103
+
]
2104
+
2105
+
[[package]]
2106
+
name = "jacquard-identity"
2107
+
version = "0.9.2"
2108
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2109
+
checksum = "1ef714cacebfca486558a9f8e205daf466bfba0466c4d0c450fd6d0252400a53"
2110
+
dependencies = [
2111
+
"bon",
2112
+
"bytes",
2113
+
"hickory-resolver",
2114
+
"http",
2115
+
"jacquard-api",
2116
+
"jacquard-common",
2117
+
"jacquard-lexicon",
2118
+
"miette",
2119
+
"mini-moka",
2120
+
"percent-encoding",
2121
+
"reqwest",
2122
+
"serde",
2123
+
"serde_html_form",
2124
+
"serde_json",
2125
+
"thiserror 2.0.17",
2126
+
"tokio",
2127
+
"trait-variant",
2128
+
"url",
2129
+
"urlencoding",
2130
+
]
2131
+
2132
+
[[package]]
2133
+
name = "jacquard-lexicon"
2134
+
version = "0.9.2"
2135
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2136
+
checksum = "de87f2c938faea1b1f1b32d5b9e0c870e7b5bb5efbf96e3692ae2d8f6b2beb7a"
2137
+
dependencies = [
2138
+
"cid",
2139
+
"dashmap 6.1.0",
2140
+
"heck 0.5.0",
2141
+
"inventory",
2142
+
"jacquard-common",
2143
+
"miette",
2144
+
"multihash",
2145
+
"prettyplease",
2146
+
"proc-macro2",
2147
+
"quote",
2148
+
"serde",
2149
+
"serde_ipld_dagcbor",
2150
+
"serde_json",
2151
+
"serde_repr",
2152
+
"serde_with",
2153
+
"sha2",
2154
+
"syn 2.0.111",
2155
+
"thiserror 2.0.17",
2156
+
"unicode-segmentation",
2157
+
]
2158
+
2159
+
[[package]]
2160
+
name = "jacquard-oauth"
2161
+
version = "0.9.2"
2162
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2163
+
checksum = "aafe9b4b2160cb57cd48d02d84d2c09706853d098e053baacb06a59fcd59a898"
2164
+
dependencies = [
2165
+
"base64 0.22.1",
2166
+
"bytes",
2167
+
"chrono",
2168
+
"dashmap 6.1.0",
2169
+
"elliptic-curve",
2170
+
"http",
2171
+
"jacquard-common",
2172
+
"jacquard-identity",
2173
+
"jose-jwa",
2174
+
"jose-jwk",
2175
+
"miette",
2176
+
"p256",
2177
+
"rand 0.8.5",
2178
+
"rouille",
2179
+
"serde",
2180
+
"serde_html_form",
2181
+
"serde_json",
2182
+
"sha2",
2183
+
"smol_str",
2184
+
"thiserror 2.0.17",
2185
+
"tokio",
2186
+
"trait-variant",
2187
+
"url",
2188
+
"webbrowser",
2189
+
]
2190
+
2191
+
[[package]]
2192
+
name = "jacquard-repo"
2193
+
version = "0.9.2"
2194
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2195
+
checksum = "2ccdadfea11df142fbfb11cf7e5c1f7b8c0548758dedb0ce0eac182777f91f18"
2196
+
dependencies = [
2197
+
"bytes",
2198
+
"cid",
2199
+
"ed25519-dalek",
2200
+
"iroh-car",
2201
+
"jacquard-common",
2202
+
"jacquard-derive",
2203
+
"k256",
2204
+
"miette",
2205
+
"multihash",
2206
+
"n0-future",
2207
+
"p256",
2208
+
"serde",
2209
+
"serde_bytes",
2210
+
"serde_ipld_dagcbor",
2211
+
"sha2",
2212
+
"smol_str",
2213
+
"thiserror 2.0.17",
2214
+
"tokio",
2215
+
"trait-variant",
2216
+
]
2217
+
2218
+
[[package]]
2219
+
name = "jni"
2220
+
version = "0.21.1"
2221
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2222
+
checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97"
2223
+
dependencies = [
2224
+
"cesu8",
2225
+
"cfg-if",
2226
+
"combine",
2227
+
"jni-sys",
2228
+
"log",
2229
+
"thiserror 1.0.69",
2230
+
"walkdir",
2231
+
"windows-sys 0.45.0",
2232
+
]
2233
+
2234
+
[[package]]
2235
+
name = "jni-sys"
2236
+
version = "0.3.0"
2237
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2238
+
checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130"
2239
+
2240
+
[[package]]
2241
+
name = "jose-b64"
2242
+
version = "0.1.2"
2243
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2244
+
checksum = "bec69375368709666b21c76965ce67549f2d2db7605f1f8707d17c9656801b56"
2245
+
dependencies = [
2246
+
"base64ct",
2247
+
"serde",
2248
+
"subtle",
2249
+
"zeroize",
2250
+
]
2251
+
2252
+
[[package]]
2253
+
name = "jose-jwa"
2254
+
version = "0.1.2"
2255
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2256
+
checksum = "9ab78e053fe886a351d67cf0d194c000f9d0dcb92906eb34d853d7e758a4b3a7"
2257
+
dependencies = [
2258
+
"serde",
2259
+
]
2260
+
2261
+
[[package]]
2262
+
name = "jose-jwk"
2263
+
version = "0.1.2"
2264
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2265
+
checksum = "280fa263807fe0782ecb6f2baadc28dffc04e00558a58e33bfdb801d11fd58e7"
2266
+
dependencies = [
2267
+
"jose-b64",
2268
+
"jose-jwa",
2269
+
"p256",
2270
+
"p384",
2271
+
"rsa",
2272
+
"serde",
2273
+
"zeroize",
2274
+
]
2275
+
2276
+
[[package]]
2277
+
name = "js-sys"
2278
+
version = "0.3.83"
2279
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2280
+
checksum = "464a3709c7f55f1f721e5389aa6ea4e3bc6aba669353300af094b29ffbdde1d8"
2281
+
dependencies = [
2282
+
"once_cell",
2283
+
"wasm-bindgen",
2284
+
]
2285
+
2286
+
[[package]]
2287
+
name = "jsonwebtoken"
2288
+
version = "10.2.0"
2289
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2290
+
checksum = "c76e1c7d7df3e34443b3621b459b066a7b79644f059fc8b2db7070c825fd417e"
2291
+
dependencies = [
2292
+
"base64 0.22.1",
2293
+
"ed25519-dalek",
2294
+
"getrandom 0.2.16",
2295
+
"hmac",
2296
+
"js-sys",
2297
+
"p256",
2298
+
"p384",
2299
+
"pem",
2300
+
"rand 0.8.5",
2301
+
"rsa",
2302
+
"serde",
2303
+
"serde_json",
2304
+
"sha2",
2305
+
"signature",
2306
+
"simple_asn1",
2307
+
]
2308
+
2309
+
[[package]]
2310
+
name = "k256"
2311
+
version = "0.13.4"
2312
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2313
+
checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b"
2314
+
dependencies = [
2315
+
"cfg-if",
2316
+
"ecdsa",
2317
+
"elliptic-curve",
2318
+
"once_cell",
2319
+
"sha2",
2320
+
"signature",
2321
+
]
2322
+
2323
+
[[package]]
2324
+
name = "langtag"
2325
+
version = "0.4.0"
2326
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2327
+
checksum = "9ecb4c689a30e48ebeaa14237f34037e300dd072e6ad21a9ec72e810ff3c6600"
2328
+
dependencies = [
2329
+
"serde",
2330
+
"static-regular-grammar",
2331
+
"thiserror 1.0.69",
2332
+
]
2333
+
2334
+
[[package]]
2335
+
name = "lazy_static"
2336
+
version = "1.5.0"
2337
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2338
+
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
2339
+
dependencies = [
2340
+
"spin 0.9.8",
2341
+
]
2342
+
2343
+
[[package]]
2344
+
name = "libc"
2345
+
version = "0.2.178"
2346
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2347
+
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
2348
+
2349
+
[[package]]
2350
+
name = "libm"
2351
+
version = "0.2.15"
2352
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2353
+
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
2354
+
2355
+
[[package]]
2356
+
name = "libredox"
2357
+
version = "0.1.10"
2358
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2359
+
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb"
2360
+
dependencies = [
2361
+
"bitflags",
2362
+
"libc",
2363
+
"redox_syscall",
2364
+
]
2365
+
2366
+
[[package]]
2367
+
name = "libsqlite3-sys"
2368
+
version = "0.30.1"
2369
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2370
+
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
2371
+
dependencies = [
2372
+
"pkg-config",
2373
+
"vcpkg",
2374
+
]
2375
+
2376
+
[[package]]
2377
+
name = "linked-hash-map"
2378
+
version = "0.5.6"
2379
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2380
+
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
2381
+
2382
+
[[package]]
2383
+
name = "linux-raw-sys"
2384
+
version = "0.11.0"
2385
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2386
+
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
2387
+
2388
+
[[package]]
2389
+
name = "litemap"
2390
+
version = "0.8.1"
2391
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2392
+
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
2393
+
2394
+
[[package]]
2395
+
name = "lock_api"
2396
+
version = "0.4.14"
2397
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2398
+
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
2399
+
dependencies = [
2400
+
"scopeguard",
2401
+
]
2402
+
2403
+
[[package]]
2404
+
name = "log"
2405
+
version = "0.4.28"
2406
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2407
+
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
2408
+
2409
+
[[package]]
2410
+
name = "loom"
2411
+
version = "0.7.2"
2412
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2413
+
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
2414
+
dependencies = [
2415
+
"cfg-if",
2416
+
"generator",
2417
+
"scoped-tls",
2418
+
"tracing",
2419
+
"tracing-subscriber",
2420
+
]
2421
+
2422
+
[[package]]
2423
+
name = "lru-cache"
2424
+
version = "0.1.2"
2425
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2426
+
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
2427
+
dependencies = [
2428
+
"linked-hash-map",
2429
+
]
2430
+
2431
+
[[package]]
2432
+
name = "lru-slab"
2433
+
version = "0.1.2"
2434
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2435
+
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
2436
+
2437
+
[[package]]
2438
+
name = "mac"
2439
+
version = "0.1.1"
2440
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2441
+
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
2442
+
2443
+
[[package]]
2444
+
name = "markup5ever"
2445
+
version = "0.12.1"
2446
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2447
+
checksum = "16ce3abbeba692c8b8441d036ef91aea6df8da2c6b6e21c7e14d3c18e526be45"
2448
+
dependencies = [
2449
+
"log",
2450
+
"phf",
2451
+
"phf_codegen",
2452
+
"string_cache",
2453
+
"string_cache_codegen",
2454
+
"tendril",
2455
+
]
2456
+
2457
+
[[package]]
2458
+
name = "markup5ever_rcdom"
2459
+
version = "0.3.0"
2460
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2461
+
checksum = "edaa21ab3701bfee5099ade5f7e1f84553fd19228cf332f13cd6e964bf59be18"
2462
+
dependencies = [
2463
+
"html5ever",
2464
+
"markup5ever",
2465
+
"tendril",
2466
+
"xml5ever",
2467
+
]
2468
+
2469
+
[[package]]
2470
+
name = "match-lookup"
2471
+
version = "0.1.1"
2472
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2473
+
checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e"
2474
+
dependencies = [
2475
+
"proc-macro2",
2476
+
"quote",
2477
+
"syn 1.0.109",
2478
+
]
2479
+
2480
+
[[package]]
2481
+
name = "matchers"
2482
+
version = "0.2.0"
2483
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2484
+
checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9"
2485
+
dependencies = [
2486
+
"regex-automata",
2487
+
]
2488
+
2489
+
[[package]]
2490
+
name = "matchit"
2491
+
version = "0.8.4"
2492
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2493
+
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
2494
+
2495
+
[[package]]
2496
+
name = "md-5"
2497
+
version = "0.10.6"
2498
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2499
+
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
2500
+
dependencies = [
2501
+
"cfg-if",
2502
+
"digest",
2503
+
]
2504
+
2505
+
[[package]]
2506
+
name = "memchr"
2507
+
version = "2.7.6"
2508
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2509
+
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
2510
+
2511
+
[[package]]
2512
+
name = "miette"
2513
+
version = "7.6.0"
2514
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2515
+
checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"
2516
+
dependencies = [
2517
+
"cfg-if",
2518
+
"miette-derive",
2519
+
"unicode-width",
2520
+
]
2521
+
2522
+
[[package]]
2523
+
name = "miette-derive"
2524
+
version = "7.6.0"
2525
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2526
+
checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
2527
+
dependencies = [
2528
+
"proc-macro2",
2529
+
"quote",
2530
+
"syn 2.0.111",
2531
+
]
2532
+
2533
+
[[package]]
2534
+
name = "mime"
2535
+
version = "0.3.17"
2536
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2537
+
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
2538
+
2539
+
[[package]]
2540
+
name = "mime_guess"
2541
+
version = "2.0.5"
2542
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2543
+
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
2544
+
dependencies = [
2545
+
"mime",
2546
+
"unicase",
2547
+
]
2548
+
2549
+
[[package]]
2550
+
name = "mini-moka"
2551
+
version = "0.10.3"
2552
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2553
+
checksum = "c325dfab65f261f386debee8b0969da215b3fa0037e74c8a1234db7ba986d803"
2554
+
dependencies = [
2555
+
"crossbeam-channel",
2556
+
"crossbeam-utils",
2557
+
"dashmap 5.5.3",
2558
+
"skeptic",
2559
+
"smallvec",
2560
+
"tagptr",
2561
+
"triomphe",
2562
+
]
2563
+
2564
+
[[package]]
2565
+
name = "minimal-lexical"
2566
+
version = "0.2.1"
2567
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2568
+
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
2569
+
2570
+
[[package]]
2571
+
name = "miniz_oxide"
2572
+
version = "0.8.9"
2573
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2574
+
checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
2575
+
dependencies = [
2576
+
"adler2",
2577
+
"simd-adler32",
2578
+
]
2579
+
2580
+
[[package]]
2581
+
name = "mio"
2582
+
version = "1.1.0"
2583
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2584
+
checksum = "69d83b0086dc8ecf3ce9ae2874b2d1290252e2a30720bea58a5c6639b0092873"
2585
+
dependencies = [
2586
+
"libc",
2587
+
"wasi",
2588
+
"windows-sys 0.61.2",
2589
+
]
2590
+
2591
+
[[package]]
2592
+
name = "multibase"
2593
+
version = "0.9.2"
2594
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2595
+
checksum = "8694bb4835f452b0e3bb06dbebb1d6fc5385b6ca1caf2e55fd165c042390ec77"
2596
+
dependencies = [
2597
+
"base-x",
2598
+
"base256emoji",
2599
+
"data-encoding",
2600
+
"data-encoding-macro",
2601
+
]
2602
+
2603
+
[[package]]
2604
+
name = "multihash"
2605
+
version = "0.19.3"
2606
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2607
+
checksum = "6b430e7953c29dd6a09afc29ff0bb69c6e306329ee6794700aee27b76a1aea8d"
2608
+
dependencies = [
2609
+
"core2",
2610
+
"serde",
2611
+
"unsigned-varint 0.8.0",
2612
+
]
2613
+
2614
+
[[package]]
2615
+
name = "multipart"
2616
+
version = "0.18.0"
2617
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2618
+
checksum = "00dec633863867f29cb39df64a397cdf4a6354708ddd7759f70c7fb51c5f9182"
2619
+
dependencies = [
2620
+
"buf_redux",
2621
+
"httparse",
2622
+
"log",
2623
+
"mime",
2624
+
"mime_guess",
2625
+
"quick-error",
2626
+
"rand 0.8.5",
2627
+
"safemem",
2628
+
"tempfile",
2629
+
"twoway",
2630
+
]
2631
+
2632
+
[[package]]
2633
+
name = "n0-future"
2634
+
version = "0.1.3"
2635
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2636
+
checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794"
2637
+
dependencies = [
2638
+
"cfg_aliases",
2639
+
"derive_more",
2640
+
"futures-buffered",
2641
+
"futures-lite",
2642
+
"futures-util",
2643
+
"js-sys",
2644
+
"pin-project",
2645
+
"send_wrapper",
2646
+
"tokio",
2647
+
"tokio-util",
2648
+
"wasm-bindgen",
2649
+
"wasm-bindgen-futures",
2650
+
"web-time",
2651
+
]
2652
+
2653
+
[[package]]
2654
+
name = "native-tls"
2655
+
version = "0.2.14"
2656
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2657
+
checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e"
2658
+
dependencies = [
2659
+
"libc",
2660
+
"log",
2661
+
"openssl",
2662
+
"openssl-probe",
2663
+
"openssl-sys",
2664
+
"schannel",
2665
+
"security-framework",
2666
+
"security-framework-sys",
2667
+
"tempfile",
2668
+
]
2669
+
2670
+
[[package]]
2671
+
name = "ndk-context"
2672
+
version = "0.1.1"
2673
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2674
+
checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b"
2675
+
2676
+
[[package]]
2677
+
name = "new_debug_unreachable"
2678
+
version = "1.0.6"
2679
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2680
+
checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086"
2681
+
2682
+
[[package]]
2683
+
name = "nom"
2684
+
version = "7.1.3"
2685
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2686
+
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
2687
+
dependencies = [
2688
+
"memchr",
2689
+
"minimal-lexical",
2690
+
]
2691
+
2692
+
[[package]]
2693
+
name = "nu-ansi-term"
2694
+
version = "0.50.3"
2695
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2696
+
checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5"
2697
+
dependencies = [
2698
+
"windows-sys 0.61.2",
2699
+
]
2700
+
2701
+
[[package]]
2702
+
name = "num-bigint"
2703
+
version = "0.4.6"
2704
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2705
+
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
2706
+
dependencies = [
2707
+
"num-integer",
2708
+
"num-traits",
2709
+
]
2710
+
2711
+
[[package]]
2712
+
name = "num-bigint-dig"
2713
+
version = "0.8.6"
2714
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2715
+
checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7"
2716
+
dependencies = [
2717
+
"lazy_static",
2718
+
"libm",
2719
+
"num-integer",
2720
+
"num-iter",
2721
+
"num-traits",
2722
+
"rand 0.8.5",
2723
+
"smallvec",
2724
+
"zeroize",
2725
+
]
2726
+
2727
+
[[package]]
2728
+
name = "num-conv"
2729
+
version = "0.1.0"
2730
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2731
+
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
2732
+
2733
+
[[package]]
2734
+
name = "num-integer"
2735
+
version = "0.1.46"
2736
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2737
+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
2738
+
dependencies = [
2739
+
"num-traits",
2740
+
]
2741
+
2742
+
[[package]]
2743
+
name = "num-iter"
2744
+
version = "0.1.45"
2745
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2746
+
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
2747
+
dependencies = [
2748
+
"autocfg",
2749
+
"num-integer",
2750
+
"num-traits",
2751
+
]
2752
+
2753
+
[[package]]
2754
+
name = "num-traits"
2755
+
version = "0.2.19"
2756
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2757
+
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
2758
+
dependencies = [
2759
+
"autocfg",
2760
+
"libm",
2761
+
]
2762
+
2763
+
[[package]]
2764
+
name = "num_cpus"
2765
+
version = "1.17.0"
2766
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2767
+
checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b"
2768
+
dependencies = [
2769
+
"hermit-abi",
2770
+
"libc",
2771
+
]
2772
+
2773
+
[[package]]
2774
+
name = "num_threads"
2775
+
version = "0.1.7"
2776
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2777
+
checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9"
2778
+
dependencies = [
2779
+
"libc",
2780
+
]
2781
+
2782
+
[[package]]
2783
+
name = "objc2"
2784
+
version = "0.6.3"
2785
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2786
+
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
2787
+
dependencies = [
2788
+
"objc2-encode",
2789
+
]
2790
+
2791
+
[[package]]
2792
+
name = "objc2-encode"
2793
+
version = "4.1.0"
2794
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2795
+
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
2796
+
2797
+
[[package]]
2798
+
name = "objc2-foundation"
2799
+
version = "0.3.2"
2800
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2801
+
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
2802
+
dependencies = [
2803
+
"bitflags",
2804
+
"objc2",
2805
+
]
2806
+
2807
+
[[package]]
2808
+
name = "once_cell"
2809
+
version = "1.21.3"
2810
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2811
+
checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
2812
+
2813
+
[[package]]
2814
+
name = "openssl"
2815
+
version = "0.10.75"
2816
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2817
+
checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328"
2818
+
dependencies = [
2819
+
"bitflags",
2820
+
"cfg-if",
2821
+
"foreign-types",
2822
+
"libc",
2823
+
"once_cell",
2824
+
"openssl-macros",
2825
+
"openssl-sys",
2826
+
]
2827
+
2828
+
[[package]]
2829
+
name = "openssl-macros"
2830
+
version = "0.1.1"
2831
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2832
+
checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
2833
+
dependencies = [
2834
+
"proc-macro2",
2835
+
"quote",
2836
+
"syn 2.0.111",
2837
+
]
2838
+
2839
+
[[package]]
2840
+
name = "openssl-probe"
2841
+
version = "0.1.6"
2842
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2843
+
checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
2844
+
2845
+
[[package]]
2846
+
name = "openssl-sys"
2847
+
version = "0.9.111"
2848
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2849
+
checksum = "82cab2d520aa75e3c58898289429321eb788c3106963d0dc886ec7a5f4adc321"
2850
+
dependencies = [
2851
+
"cc",
2852
+
"libc",
2853
+
"pkg-config",
2854
+
"vcpkg",
2855
+
]
2856
+
2857
+
[[package]]
2858
+
name = "ouroboros"
2859
+
version = "0.18.5"
2860
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2861
+
checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
2862
+
dependencies = [
2863
+
"aliasable",
2864
+
"ouroboros_macro",
2865
+
"static_assertions",
2866
+
]
2867
+
2868
+
[[package]]
2869
+
name = "ouroboros_macro"
2870
+
version = "0.18.5"
2871
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2872
+
checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
2873
+
dependencies = [
2874
+
"heck 0.4.1",
2875
+
"proc-macro2",
2876
+
"proc-macro2-diagnostics",
2877
+
"quote",
2878
+
"syn 2.0.111",
2879
+
]
2880
+
2881
+
[[package]]
2882
+
name = "p256"
2883
+
version = "0.13.2"
2884
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2885
+
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
2886
+
dependencies = [
2887
+
"ecdsa",
2888
+
"elliptic-curve",
2889
+
"primeorder",
2890
+
"sha2",
2891
+
]
2892
+
2893
+
[[package]]
2894
+
name = "p384"
2895
+
version = "0.13.1"
2896
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2897
+
checksum = "fe42f1670a52a47d448f14b6a5c61dd78fce51856e68edaa38f7ae3a46b8d6b6"
2898
+
dependencies = [
2899
+
"ecdsa",
2900
+
"elliptic-curve",
2901
+
"primeorder",
2902
+
"sha2",
2903
+
]
2904
+
2905
+
[[package]]
2906
+
name = "parking"
2907
+
version = "2.2.1"
2908
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2909
+
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
2910
+
2911
+
[[package]]
2912
+
name = "parking_lot"
2913
+
version = "0.12.5"
2914
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2915
+
checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
2916
+
dependencies = [
2917
+
"lock_api",
2918
+
"parking_lot_core",
2919
+
]
2920
+
2921
+
[[package]]
2922
+
name = "parking_lot_core"
2923
+
version = "0.9.12"
2924
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2925
+
checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
2926
+
dependencies = [
2927
+
"cfg-if",
2928
+
"libc",
2929
+
"redox_syscall",
2930
+
"smallvec",
2931
+
"windows-link 0.2.1",
2932
+
]
2933
+
2934
+
[[package]]
2935
+
name = "pem"
2936
+
version = "3.0.6"
2937
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2938
+
checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be"
2939
+
dependencies = [
2940
+
"base64 0.22.1",
2941
+
"serde_core",
2942
+
]
2943
+
2944
+
[[package]]
2945
+
name = "pem-rfc7468"
2946
+
version = "0.7.0"
2947
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2948
+
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
2949
+
dependencies = [
2950
+
"base64ct",
2951
+
]
2952
+
2953
+
[[package]]
2954
+
name = "percent-encoding"
2955
+
version = "2.3.2"
2956
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2957
+
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
2958
+
2959
+
[[package]]
2960
+
name = "phf"
2961
+
version = "0.11.3"
2962
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2963
+
checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078"
2964
+
dependencies = [
2965
+
"phf_shared",
2966
+
]
2967
+
2968
+
[[package]]
2969
+
name = "phf_codegen"
2970
+
version = "0.11.3"
2971
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2972
+
checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a"
2973
+
dependencies = [
2974
+
"phf_generator",
2975
+
"phf_shared",
2976
+
]
2977
+
2978
+
[[package]]
2979
+
name = "phf_generator"
2980
+
version = "0.11.3"
2981
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2982
+
checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d"
2983
+
dependencies = [
2984
+
"phf_shared",
2985
+
"rand 0.8.5",
2986
+
]
2987
+
2988
+
[[package]]
2989
+
name = "phf_shared"
2990
+
version = "0.11.3"
2991
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2992
+
checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5"
2993
+
dependencies = [
2994
+
"siphasher",
2995
+
]
2996
+
2997
+
[[package]]
2998
+
name = "pin-project"
2999
+
version = "1.1.10"
3000
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3001
+
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
3002
+
dependencies = [
3003
+
"pin-project-internal",
3004
+
]
3005
+
3006
+
[[package]]
3007
+
name = "pin-project-internal"
3008
+
version = "1.1.10"
3009
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3010
+
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
3011
+
dependencies = [
3012
+
"proc-macro2",
3013
+
"quote",
3014
+
"syn 2.0.111",
3015
+
]
3016
+
3017
+
[[package]]
3018
+
name = "pin-project-lite"
3019
+
version = "0.2.16"
3020
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3021
+
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
3022
+
3023
+
[[package]]
3024
+
name = "pin-utils"
3025
+
version = "0.1.0"
3026
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3027
+
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
3028
+
3029
+
[[package]]
3030
+
name = "pkcs1"
3031
+
version = "0.7.5"
3032
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3033
+
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
3034
+
dependencies = [
3035
+
"der",
3036
+
"pkcs8",
3037
+
"spki",
3038
+
]
3039
+
3040
+
[[package]]
3041
+
name = "pkcs8"
3042
+
version = "0.10.2"
3043
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3044
+
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
3045
+
dependencies = [
3046
+
"der",
3047
+
"spki",
3048
+
]
3049
+
3050
+
[[package]]
3051
+
name = "pkg-config"
3052
+
version = "0.3.32"
3053
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3054
+
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
3055
+
3056
+
[[package]]
3057
+
name = "potential_utf"
3058
+
version = "0.1.4"
3059
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3060
+
checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77"
3061
+
dependencies = [
3062
+
"zerovec",
3063
+
]
3064
+
3065
+
[[package]]
3066
+
name = "powerfmt"
3067
+
version = "0.2.0"
3068
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3069
+
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
3070
+
3071
+
[[package]]
3072
+
name = "ppv-lite86"
3073
+
version = "0.2.21"
3074
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3075
+
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
3076
+
dependencies = [
3077
+
"zerocopy",
3078
+
]
3079
+
3080
+
[[package]]
3081
+
name = "precomputed-hash"
3082
+
version = "0.1.1"
3083
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3084
+
checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
3085
+
3086
+
[[package]]
3087
+
name = "prettyplease"
3088
+
version = "0.2.37"
3089
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3090
+
checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b"
3091
+
dependencies = [
3092
+
"proc-macro2",
3093
+
"syn 2.0.111",
3094
+
]
3095
+
3096
+
[[package]]
3097
+
name = "primeorder"
3098
+
version = "0.13.6"
3099
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3100
+
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
3101
+
dependencies = [
3102
+
"elliptic-curve",
3103
+
]
3104
+
3105
+
[[package]]
3106
+
name = "proc-macro-error"
3107
+
version = "1.0.4"
3108
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3109
+
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
3110
+
dependencies = [
3111
+
"proc-macro-error-attr",
3112
+
"proc-macro2",
3113
+
"quote",
3114
+
"syn 1.0.109",
3115
+
"version_check",
3116
+
]
3117
+
3118
+
[[package]]
3119
+
name = "proc-macro-error-attr"
3120
+
version = "1.0.4"
3121
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3122
+
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
3123
+
dependencies = [
3124
+
"proc-macro2",
3125
+
"quote",
3126
+
"version_check",
3127
+
]
3128
+
3129
+
[[package]]
3130
+
name = "proc-macro2"
3131
+
version = "1.0.103"
3132
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3133
+
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
3134
+
dependencies = [
3135
+
"unicode-ident",
3136
+
]
3137
+
3138
+
[[package]]
3139
+
name = "proc-macro2-diagnostics"
3140
+
version = "0.10.1"
3141
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3142
+
checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
3143
+
dependencies = [
3144
+
"proc-macro2",
3145
+
"quote",
3146
+
"syn 2.0.111",
3147
+
"version_check",
3148
+
"yansi",
3149
+
]
3150
+
3151
+
[[package]]
3152
+
name = "pulldown-cmark"
3153
+
version = "0.9.6"
3154
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3155
+
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
3156
+
dependencies = [
3157
+
"bitflags",
3158
+
"memchr",
3159
+
"unicase",
3160
+
]
3161
+
3162
+
[[package]]
3163
+
name = "quick-error"
3164
+
version = "1.2.3"
3165
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3166
+
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
3167
+
3168
+
[[package]]
3169
+
name = "quinn"
3170
+
version = "0.11.9"
3171
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3172
+
checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20"
3173
+
dependencies = [
3174
+
"bytes",
3175
+
"cfg_aliases",
3176
+
"pin-project-lite",
3177
+
"quinn-proto",
3178
+
"quinn-udp",
3179
+
"rustc-hash",
3180
+
"rustls",
3181
+
"socket2 0.6.1",
3182
+
"thiserror 2.0.17",
3183
+
"tokio",
3184
+
"tracing",
3185
+
"web-time",
3186
+
]
3187
+
3188
+
[[package]]
3189
+
name = "quinn-proto"
3190
+
version = "0.11.13"
3191
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3192
+
checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31"
3193
+
dependencies = [
3194
+
"bytes",
3195
+
"getrandom 0.3.4",
3196
+
"lru-slab",
3197
+
"rand 0.9.2",
3198
+
"ring",
3199
+
"rustc-hash",
3200
+
"rustls",
3201
+
"rustls-pki-types",
3202
+
"slab",
3203
+
"thiserror 2.0.17",
3204
+
"tinyvec",
3205
+
"tracing",
3206
+
"web-time",
3207
+
]
3208
+
3209
+
[[package]]
3210
+
name = "quinn-udp"
3211
+
version = "0.5.14"
3212
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3213
+
checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd"
3214
+
dependencies = [
3215
+
"cfg_aliases",
3216
+
"libc",
3217
+
"once_cell",
3218
+
"socket2 0.6.1",
3219
+
"tracing",
3220
+
"windows-sys 0.60.2",
3221
+
]
3222
+
3223
+
[[package]]
3224
+
name = "quote"
3225
+
version = "1.0.42"
3226
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3227
+
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
3228
+
dependencies = [
3229
+
"proc-macro2",
3230
+
]
3231
+
3232
+
[[package]]
3233
+
name = "r-efi"
3234
+
version = "5.3.0"
3235
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3236
+
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
3237
+
3238
+
[[package]]
3239
+
name = "rand"
3240
+
version = "0.8.5"
3241
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3242
+
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
3243
+
dependencies = [
3244
+
"libc",
3245
+
"rand_chacha 0.3.1",
3246
+
"rand_core 0.6.4",
3247
+
]
3248
+
3249
+
[[package]]
3250
+
name = "rand"
3251
+
version = "0.9.2"
3252
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3253
+
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
3254
+
dependencies = [
3255
+
"rand_chacha 0.9.0",
3256
+
"rand_core 0.9.3",
3257
+
]
3258
+
3259
+
[[package]]
3260
+
name = "rand_chacha"
3261
+
version = "0.3.1"
3262
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3263
+
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
3264
+
dependencies = [
3265
+
"ppv-lite86",
3266
+
"rand_core 0.6.4",
3267
+
]
3268
+
3269
+
[[package]]
3270
+
name = "rand_chacha"
3271
+
version = "0.9.0"
3272
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3273
+
checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
3274
+
dependencies = [
3275
+
"ppv-lite86",
3276
+
"rand_core 0.9.3",
3277
+
]
3278
+
3279
+
[[package]]
3280
+
name = "rand_core"
3281
+
version = "0.6.4"
3282
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3283
+
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
3284
+
dependencies = [
3285
+
"getrandom 0.2.16",
3286
+
]
3287
+
3288
+
[[package]]
3289
+
name = "rand_core"
3290
+
version = "0.9.3"
3291
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3292
+
checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
3293
+
dependencies = [
3294
+
"getrandom 0.3.4",
3295
+
]
3296
+
3297
+
[[package]]
3298
+
name = "range-traits"
3299
+
version = "0.3.2"
3300
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3301
+
checksum = "d20581732dd76fa913c7dff1a2412b714afe3573e94d41c34719de73337cc8ab"
3302
+
3303
+
[[package]]
3304
+
name = "redox_syscall"
3305
+
version = "0.5.18"
3306
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3307
+
checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
3308
+
dependencies = [
3309
+
"bitflags",
3310
+
]
3311
+
3312
+
[[package]]
3313
+
name = "ref-cast"
3314
+
version = "1.0.25"
3315
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3316
+
checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d"
3317
+
dependencies = [
3318
+
"ref-cast-impl",
3319
+
]
3320
+
3321
+
[[package]]
3322
+
name = "ref-cast-impl"
3323
+
version = "1.0.25"
3324
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3325
+
checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da"
3326
+
dependencies = [
3327
+
"proc-macro2",
3328
+
"quote",
3329
+
"syn 2.0.111",
3330
+
]
3331
+
3332
+
[[package]]
3333
+
name = "regex"
3334
+
version = "1.12.2"
3335
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3336
+
checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4"
3337
+
dependencies = [
3338
+
"aho-corasick",
3339
+
"memchr",
3340
+
"regex-automata",
3341
+
"regex-syntax",
3342
+
]
3343
+
3344
+
[[package]]
3345
+
name = "regex-automata"
3346
+
version = "0.4.13"
3347
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3348
+
checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c"
3349
+
dependencies = [
3350
+
"aho-corasick",
3351
+
"memchr",
3352
+
"regex-syntax",
3353
+
]
3354
+
3355
+
[[package]]
3356
+
name = "regex-lite"
3357
+
version = "0.1.8"
3358
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3359
+
checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da"
3360
+
3361
+
[[package]]
3362
+
name = "regex-syntax"
3363
+
version = "0.8.8"
3364
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3365
+
checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58"
3366
+
3367
+
[[package]]
3368
+
name = "reqwest"
3369
+
version = "0.12.24"
3370
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3371
+
checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f"
3372
+
dependencies = [
3373
+
"async-compression",
3374
+
"base64 0.22.1",
3375
+
"bytes",
3376
+
"encoding_rs",
3377
+
"futures-core",
3378
+
"futures-util",
3379
+
"h2",
3380
+
"http",
3381
+
"http-body",
3382
+
"http-body-util",
3383
+
"hyper",
3384
+
"hyper-rustls",
3385
+
"hyper-tls",
3386
+
"hyper-util",
3387
+
"js-sys",
3388
+
"log",
3389
+
"mime",
3390
+
"native-tls",
3391
+
"percent-encoding",
3392
+
"pin-project-lite",
3393
+
"quinn",
3394
+
"rustls",
3395
+
"rustls-pki-types",
3396
+
"serde",
3397
+
"serde_json",
3398
+
"serde_urlencoded",
3399
+
"sync_wrapper",
3400
+
"tokio",
3401
+
"tokio-native-tls",
3402
+
"tokio-rustls",
3403
+
"tokio-util",
3404
+
"tower",
3405
+
"tower-http",
3406
+
"tower-service",
3407
+
"url",
3408
+
"wasm-bindgen",
3409
+
"wasm-bindgen-futures",
3410
+
"wasm-streams",
3411
+
"web-sys",
3412
+
"webpki-roots 1.0.4",
3413
+
]
3414
+
3415
+
[[package]]
3416
+
name = "resolv-conf"
3417
+
version = "0.7.6"
3418
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3419
+
checksum = "1e061d1b48cb8d38042de4ae0a7a6401009d6143dc80d2e2d6f31f0bdd6470c7"
3420
+
3421
+
[[package]]
3422
+
name = "rfc6979"
3423
+
version = "0.4.0"
3424
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3425
+
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
3426
+
dependencies = [
3427
+
"hmac",
3428
+
"subtle",
3429
+
]
3430
+
3431
+
[[package]]
3432
+
name = "ring"
3433
+
version = "0.17.14"
3434
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3435
+
checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
3436
+
dependencies = [
3437
+
"cc",
3438
+
"cfg-if",
3439
+
"getrandom 0.2.16",
3440
+
"libc",
3441
+
"untrusted",
3442
+
"windows-sys 0.52.0",
3443
+
]
3444
+
3445
+
[[package]]
3446
+
name = "rouille"
3447
+
version = "3.6.2"
3448
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3449
+
checksum = "3716fbf57fc1084d7a706adf4e445298d123e4a44294c4e8213caf1b85fcc921"
3450
+
dependencies = [
3451
+
"base64 0.13.1",
3452
+
"brotli",
3453
+
"chrono",
3454
+
"deflate",
3455
+
"filetime",
3456
+
"multipart",
3457
+
"percent-encoding",
3458
+
"rand 0.8.5",
3459
+
"serde",
3460
+
"serde_derive",
3461
+
"serde_json",
3462
+
"sha1_smol",
3463
+
"threadpool",
3464
+
"time",
3465
+
"tiny_http",
3466
+
"url",
3467
+
]
3468
+
3469
+
[[package]]
3470
+
name = "rsa"
3471
+
version = "0.9.9"
3472
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3473
+
checksum = "40a0376c50d0358279d9d643e4bf7b7be212f1f4ff1da9070a7b54d22ef75c88"
3474
+
dependencies = [
3475
+
"const-oid",
3476
+
"digest",
3477
+
"num-bigint-dig",
3478
+
"num-integer",
3479
+
"num-traits",
3480
+
"pkcs1",
3481
+
"pkcs8",
3482
+
"rand_core 0.6.4",
3483
+
"signature",
3484
+
"spki",
3485
+
"subtle",
3486
+
"zeroize",
3487
+
]
3488
+
3489
+
[[package]]
3490
+
name = "rustc-hash"
3491
+
version = "2.1.1"
3492
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3493
+
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
3494
+
3495
+
[[package]]
3496
+
name = "rustc_version"
3497
+
version = "0.4.1"
3498
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3499
+
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
3500
+
dependencies = [
3501
+
"semver",
3502
+
]
3503
+
3504
+
[[package]]
3505
+
name = "rustix"
3506
+
version = "1.1.2"
3507
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3508
+
checksum = "cd15f8a2c5551a84d56efdc1cd049089e409ac19a3072d5037a17fd70719ff3e"
3509
+
dependencies = [
3510
+
"bitflags",
3511
+
"errno",
3512
+
"libc",
3513
+
"linux-raw-sys",
3514
+
"windows-sys 0.61.2",
3515
+
]
3516
+
3517
+
[[package]]
3518
+
name = "rustls"
3519
+
version = "0.23.35"
3520
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3521
+
checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f"
3522
+
dependencies = [
3523
+
"once_cell",
3524
+
"ring",
3525
+
"rustls-pki-types",
3526
+
"rustls-webpki",
3527
+
"subtle",
3528
+
"zeroize",
3529
+
]
3530
+
3531
+
[[package]]
3532
+
name = "rustls-pki-types"
3533
+
version = "1.13.1"
3534
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3535
+
checksum = "708c0f9d5f54ba0272468c1d306a52c495b31fa155e91bc25371e6df7996908c"
3536
+
dependencies = [
3537
+
"web-time",
3538
+
"zeroize",
3539
+
]
3540
+
3541
+
[[package]]
3542
+
name = "rustls-webpki"
3543
+
version = "0.103.8"
3544
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3545
+
checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52"
3546
+
dependencies = [
3547
+
"ring",
3548
+
"rustls-pki-types",
3549
+
"untrusted",
3550
+
]
3551
+
3552
+
[[package]]
3553
+
name = "rustversion"
3554
+
version = "1.0.22"
3555
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3556
+
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
3557
+
3558
+
[[package]]
3559
+
name = "ryu"
3560
+
version = "1.0.20"
3561
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3562
+
checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
3563
+
3564
+
[[package]]
3565
+
name = "safemem"
3566
+
version = "0.3.3"
3567
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3568
+
checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072"
3569
+
3570
+
[[package]]
3571
+
name = "same-file"
3572
+
version = "1.0.6"
3573
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3574
+
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
3575
+
dependencies = [
3576
+
"winapi-util",
3577
+
]
3578
+
3579
+
[[package]]
3580
+
name = "schannel"
3581
+
version = "0.1.28"
3582
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3583
+
checksum = "891d81b926048e76efe18581bf793546b4c0eaf8448d72be8de2bbee5fd166e1"
3584
+
dependencies = [
3585
+
"windows-sys 0.61.2",
3586
+
]
3587
+
3588
+
[[package]]
3589
+
name = "schemars"
3590
+
version = "0.9.0"
3591
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3592
+
checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
3593
+
dependencies = [
3594
+
"dyn-clone",
3595
+
"ref-cast",
3596
+
"serde",
3597
+
"serde_json",
3598
+
]
3599
+
3600
+
[[package]]
3601
+
name = "schemars"
3602
+
version = "1.1.0"
3603
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3604
+
checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289"
3605
+
dependencies = [
3606
+
"dyn-clone",
3607
+
"ref-cast",
3608
+
"serde",
3609
+
"serde_json",
3610
+
]
3611
+
3612
+
[[package]]
3613
+
name = "scoped-tls"
3614
+
version = "1.0.1"
3615
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3616
+
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
3617
+
3618
+
[[package]]
3619
+
name = "scopeguard"
3620
+
version = "1.2.0"
3621
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3622
+
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
3623
+
3624
+
[[package]]
3625
+
name = "sec1"
3626
+
version = "0.7.3"
3627
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3628
+
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
3629
+
dependencies = [
3630
+
"base16ct",
3631
+
"der",
3632
+
"generic-array",
3633
+
"pkcs8",
3634
+
"subtle",
3635
+
"zeroize",
3636
+
]
3637
+
3638
+
[[package]]
3639
+
name = "security-framework"
3640
+
version = "2.11.1"
3641
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3642
+
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
3643
+
dependencies = [
3644
+
"bitflags",
3645
+
"core-foundation 0.9.4",
3646
+
"core-foundation-sys",
3647
+
"libc",
3648
+
"security-framework-sys",
3649
+
]
3650
+
3651
+
[[package]]
3652
+
name = "security-framework-sys"
3653
+
version = "2.15.0"
3654
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3655
+
checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0"
3656
+
dependencies = [
3657
+
"core-foundation-sys",
3658
+
"libc",
3659
+
]
3660
+
3661
+
[[package]]
3662
+
name = "semver"
3663
+
version = "1.0.27"
3664
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3665
+
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
3666
+
dependencies = [
3667
+
"serde",
3668
+
"serde_core",
3669
+
]
3670
+
3671
+
[[package]]
3672
+
name = "send_wrapper"
3673
+
version = "0.6.0"
3674
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3675
+
checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73"
3676
+
3677
+
[[package]]
3678
+
name = "serde"
3679
+
version = "1.0.228"
3680
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3681
+
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
3682
+
dependencies = [
3683
+
"serde_core",
3684
+
"serde_derive",
3685
+
]
3686
+
3687
+
[[package]]
3688
+
name = "serde_bytes"
3689
+
version = "0.11.19"
3690
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3691
+
checksum = "a5d440709e79d88e51ac01c4b72fc6cb7314017bb7da9eeff678aa94c10e3ea8"
3692
+
dependencies = [
3693
+
"serde",
3694
+
"serde_core",
3695
+
]
3696
+
3697
+
[[package]]
3698
+
name = "serde_core"
3699
+
version = "1.0.228"
3700
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3701
+
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
3702
+
dependencies = [
3703
+
"serde_derive",
3704
+
]
3705
+
3706
+
[[package]]
3707
+
name = "serde_derive"
3708
+
version = "1.0.228"
3709
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3710
+
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
3711
+
dependencies = [
3712
+
"proc-macro2",
3713
+
"quote",
3714
+
"syn 2.0.111",
3715
+
]
3716
+
3717
+
[[package]]
3718
+
name = "serde_html_form"
3719
+
version = "0.2.8"
3720
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3721
+
checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f"
3722
+
dependencies = [
3723
+
"form_urlencoded",
3724
+
"indexmap 2.12.1",
3725
+
"itoa",
3726
+
"ryu",
3727
+
"serde_core",
3728
+
]
3729
+
3730
+
[[package]]
3731
+
name = "serde_ipld_dagcbor"
3732
+
version = "0.6.4"
3733
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3734
+
checksum = "46182f4f08349a02b45c998ba3215d3f9de826246ba02bb9dddfe9a2a2100778"
3735
+
dependencies = [
3736
+
"cbor4ii",
3737
+
"ipld-core",
3738
+
"scopeguard",
3739
+
"serde",
3740
+
]
3741
+
3742
+
[[package]]
3743
+
name = "serde_json"
3744
+
version = "1.0.145"
3745
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3746
+
checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c"
3747
+
dependencies = [
3748
+
"itoa",
3749
+
"memchr",
3750
+
"ryu",
3751
+
"serde",
3752
+
"serde_core",
3753
+
]
3754
+
3755
+
[[package]]
3756
+
name = "serde_path_to_error"
3757
+
version = "0.1.20"
3758
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3759
+
checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457"
3760
+
dependencies = [
3761
+
"itoa",
3762
+
"serde",
3763
+
"serde_core",
3764
+
]
3765
+
3766
+
[[package]]
3767
+
name = "serde_repr"
3768
+
version = "0.1.20"
3769
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3770
+
checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c"
3771
+
dependencies = [
3772
+
"proc-macro2",
3773
+
"quote",
3774
+
"syn 2.0.111",
3775
+
]
3776
+
3777
+
[[package]]
3778
+
name = "serde_urlencoded"
3779
+
version = "0.7.1"
3780
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3781
+
checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
3782
+
dependencies = [
3783
+
"form_urlencoded",
3784
+
"itoa",
3785
+
"ryu",
3786
+
"serde",
3787
+
]
3788
+
3789
+
[[package]]
3790
+
name = "serde_with"
3791
+
version = "3.16.1"
3792
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3793
+
checksum = "4fa237f2807440d238e0364a218270b98f767a00d3dada77b1c53ae88940e2e7"
3794
+
dependencies = [
3795
+
"base64 0.22.1",
3796
+
"chrono",
3797
+
"hex",
3798
+
"indexmap 1.9.3",
3799
+
"indexmap 2.12.1",
3800
+
"schemars 0.9.0",
3801
+
"schemars 1.1.0",
3802
+
"serde_core",
3803
+
"serde_json",
3804
+
"serde_with_macros",
3805
+
"time",
3806
+
]
3807
+
3808
+
[[package]]
3809
+
name = "serde_with_macros"
3810
+
version = "3.16.1"
3811
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3812
+
checksum = "52a8e3ca0ca629121f70ab50f95249e5a6f925cc0f6ffe8256c45b728875706c"
3813
+
dependencies = [
3814
+
"darling",
3815
+
"proc-macro2",
3816
+
"quote",
3817
+
"syn 2.0.111",
3818
+
]
3819
+
3820
+
[[package]]
3821
+
name = "sha1"
3822
+
version = "0.10.6"
3823
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3824
+
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
3825
+
dependencies = [
3826
+
"cfg-if",
3827
+
"cpufeatures",
3828
+
"digest",
3829
+
]
3830
+
3831
+
[[package]]
3832
+
name = "sha1_smol"
3833
+
version = "1.0.1"
3834
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3835
+
checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d"
3836
+
3837
+
[[package]]
3838
+
name = "sha2"
3839
+
version = "0.10.9"
3840
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3841
+
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
3842
+
dependencies = [
3843
+
"cfg-if",
3844
+
"cpufeatures",
3845
+
"digest",
3846
+
]
3847
+
3848
+
[[package]]
3849
+
name = "sharded-slab"
3850
+
version = "0.1.7"
3851
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3852
+
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
3853
+
dependencies = [
3854
+
"lazy_static",
3855
+
]
3856
+
3857
+
[[package]]
3858
+
name = "shlex"
3859
+
version = "1.3.0"
3860
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3861
+
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
3862
+
3863
+
[[package]]
3864
+
name = "signature"
3865
+
version = "2.2.0"
3866
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3867
+
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
3868
+
dependencies = [
3869
+
"digest",
3870
+
"rand_core 0.6.4",
3871
+
]
3872
+
3873
+
[[package]]
3874
+
name = "simd-adler32"
3875
+
version = "0.3.7"
3876
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3877
+
checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe"
3878
+
3879
+
[[package]]
3880
+
name = "simple_asn1"
3881
+
version = "0.6.3"
3882
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3883
+
checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb"
3884
+
dependencies = [
3885
+
"num-bigint",
3886
+
"num-traits",
3887
+
"thiserror 2.0.17",
3888
+
"time",
3889
+
]
3890
+
3891
+
[[package]]
3892
+
name = "siphasher"
3893
+
version = "1.0.1"
3894
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3895
+
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
3896
+
3897
+
[[package]]
3898
+
name = "skeptic"
3899
+
version = "0.13.7"
3900
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3901
+
checksum = "16d23b015676c90a0f01c197bfdc786c20342c73a0afdda9025adb0bc42940a8"
3902
+
dependencies = [
3903
+
"bytecount",
3904
+
"cargo_metadata",
3905
+
"error-chain",
3906
+
"glob",
3907
+
"pulldown-cmark",
3908
+
"tempfile",
3909
+
"walkdir",
3910
+
]
3911
+
3912
+
[[package]]
3913
+
name = "slab"
3914
+
version = "0.4.11"
3915
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3916
+
checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
3917
+
3918
+
[[package]]
3919
+
name = "smallvec"
3920
+
version = "1.15.1"
3921
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3922
+
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
3923
+
dependencies = [
3924
+
"serde",
3925
+
]
3926
+
3927
+
[[package]]
3928
+
name = "smol_str"
3929
+
version = "0.3.4"
3930
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3931
+
checksum = "3498b0a27f93ef1402f20eefacfaa1691272ac4eca1cdc8c596cb0a245d6cbf5"
3932
+
dependencies = [
3933
+
"borsh",
3934
+
"serde_core",
3935
+
]
3936
+
3937
+
[[package]]
3938
+
name = "socket2"
3939
+
version = "0.5.10"
3940
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3941
+
checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678"
3942
+
dependencies = [
3943
+
"libc",
3944
+
"windows-sys 0.52.0",
3945
+
]
3946
+
3947
+
[[package]]
3948
+
name = "socket2"
3949
+
version = "0.6.1"
3950
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3951
+
checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881"
3952
+
dependencies = [
3953
+
"libc",
3954
+
"windows-sys 0.60.2",
3955
+
]
3956
+
3957
+
[[package]]
3958
+
name = "spin"
3959
+
version = "0.9.8"
3960
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3961
+
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
3962
+
dependencies = [
3963
+
"lock_api",
3964
+
]
3965
+
3966
+
[[package]]
3967
+
name = "spin"
3968
+
version = "0.10.0"
3969
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3970
+
checksum = "d5fe4ccb98d9c292d56fec89a5e07da7fc4cf0dc11e156b41793132775d3e591"
3971
+
3972
+
[[package]]
3973
+
name = "spki"
3974
+
version = "0.7.3"
3975
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3976
+
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
3977
+
dependencies = [
3978
+
"base64ct",
3979
+
"der",
3980
+
]
3981
+
3982
+
[[package]]
3983
+
name = "sqlx"
3984
+
version = "0.8.6"
3985
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3986
+
checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc"
3987
+
dependencies = [
3988
+
"sqlx-core",
3989
+
"sqlx-macros",
3990
+
"sqlx-mysql",
3991
+
"sqlx-postgres",
3992
+
"sqlx-sqlite",
3993
+
]
3994
+
3995
+
[[package]]
3996
+
name = "sqlx-core"
3997
+
version = "0.8.6"
3998
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3999
+
checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
4000
+
dependencies = [
4001
+
"base64 0.22.1",
4002
+
"bytes",
4003
+
"chrono",
4004
+
"crc",
4005
+
"crossbeam-queue",
4006
+
"either",
4007
+
"event-listener",
4008
+
"futures-core",
4009
+
"futures-intrusive",
4010
+
"futures-io",
4011
+
"futures-util",
4012
+
"hashbrown 0.15.5",
4013
+
"hashlink",
4014
+
"indexmap 2.12.1",
4015
+
"log",
4016
+
"memchr",
4017
+
"once_cell",
4018
+
"percent-encoding",
4019
+
"rustls",
4020
+
"serde",
4021
+
"serde_json",
4022
+
"sha2",
4023
+
"smallvec",
4024
+
"thiserror 2.0.17",
4025
+
"tokio",
4026
+
"tokio-stream",
4027
+
"tracing",
4028
+
"url",
4029
+
"uuid",
4030
+
"webpki-roots 0.26.11",
4031
+
]
4032
+
4033
+
[[package]]
4034
+
name = "sqlx-macros"
4035
+
version = "0.8.6"
4036
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4037
+
checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d"
4038
+
dependencies = [
4039
+
"proc-macro2",
4040
+
"quote",
4041
+
"sqlx-core",
4042
+
"sqlx-macros-core",
4043
+
"syn 2.0.111",
4044
+
]
4045
+
4046
+
[[package]]
4047
+
name = "sqlx-macros-core"
4048
+
version = "0.8.6"
4049
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4050
+
checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b"
4051
+
dependencies = [
4052
+
"dotenvy",
4053
+
"either",
4054
+
"heck 0.5.0",
4055
+
"hex",
4056
+
"once_cell",
4057
+
"proc-macro2",
4058
+
"quote",
4059
+
"serde",
4060
+
"serde_json",
4061
+
"sha2",
4062
+
"sqlx-core",
4063
+
"sqlx-mysql",
4064
+
"sqlx-postgres",
4065
+
"sqlx-sqlite",
4066
+
"syn 2.0.111",
4067
+
"tokio",
4068
+
"url",
4069
+
]
4070
+
4071
+
[[package]]
4072
+
name = "sqlx-mysql"
4073
+
version = "0.8.6"
4074
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4075
+
checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
4076
+
dependencies = [
4077
+
"atoi",
4078
+
"base64 0.22.1",
4079
+
"bitflags",
4080
+
"byteorder",
4081
+
"bytes",
4082
+
"chrono",
4083
+
"crc",
4084
+
"digest",
4085
+
"dotenvy",
4086
+
"either",
4087
+
"futures-channel",
4088
+
"futures-core",
4089
+
"futures-io",
4090
+
"futures-util",
4091
+
"generic-array",
4092
+
"hex",
4093
+
"hkdf",
4094
+
"hmac",
4095
+
"itoa",
4096
+
"log",
4097
+
"md-5",
4098
+
"memchr",
4099
+
"once_cell",
4100
+
"percent-encoding",
4101
+
"rand 0.8.5",
4102
+
"rsa",
4103
+
"serde",
4104
+
"sha1",
4105
+
"sha2",
4106
+
"smallvec",
4107
+
"sqlx-core",
4108
+
"stringprep",
4109
+
"thiserror 2.0.17",
4110
+
"tracing",
4111
+
"uuid",
4112
+
"whoami",
4113
+
]
4114
+
4115
+
[[package]]
4116
+
name = "sqlx-postgres"
4117
+
version = "0.8.6"
4118
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4119
+
checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
4120
+
dependencies = [
4121
+
"atoi",
4122
+
"base64 0.22.1",
4123
+
"bitflags",
4124
+
"byteorder",
4125
+
"chrono",
4126
+
"crc",
4127
+
"dotenvy",
4128
+
"etcetera",
4129
+
"futures-channel",
4130
+
"futures-core",
4131
+
"futures-util",
4132
+
"hex",
4133
+
"hkdf",
4134
+
"hmac",
4135
+
"home",
4136
+
"itoa",
4137
+
"log",
4138
+
"md-5",
4139
+
"memchr",
4140
+
"once_cell",
4141
+
"rand 0.8.5",
4142
+
"serde",
4143
+
"serde_json",
4144
+
"sha2",
4145
+
"smallvec",
4146
+
"sqlx-core",
4147
+
"stringprep",
4148
+
"thiserror 2.0.17",
4149
+
"tracing",
4150
+
"uuid",
4151
+
"whoami",
4152
+
]
4153
+
4154
+
[[package]]
4155
+
name = "sqlx-sqlite"
4156
+
version = "0.8.6"
4157
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4158
+
checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
4159
+
dependencies = [
4160
+
"atoi",
4161
+
"chrono",
4162
+
"flume",
4163
+
"futures-channel",
4164
+
"futures-core",
4165
+
"futures-executor",
4166
+
"futures-intrusive",
4167
+
"futures-util",
4168
+
"libsqlite3-sys",
4169
+
"log",
4170
+
"percent-encoding",
4171
+
"serde",
4172
+
"serde_urlencoded",
4173
+
"sqlx-core",
4174
+
"thiserror 2.0.17",
4175
+
"tracing",
4176
+
"url",
4177
+
"uuid",
4178
+
]
4179
+
4180
+
[[package]]
4181
+
name = "stable_deref_trait"
4182
+
version = "1.2.1"
4183
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4184
+
checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596"
4185
+
4186
+
[[package]]
4187
+
name = "static-regular-grammar"
4188
+
version = "2.0.2"
4189
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4190
+
checksum = "4f4a6c40247579acfbb138c3cd7de3dab113ab4ac6227f1b7de7d626ee667957"
4191
+
dependencies = [
4192
+
"abnf",
4193
+
"btree-range-map",
4194
+
"ciborium",
4195
+
"hex_fmt",
4196
+
"indoc",
4197
+
"proc-macro-error",
4198
+
"proc-macro2",
4199
+
"quote",
4200
+
"serde",
4201
+
"sha2",
4202
+
"syn 2.0.111",
4203
+
"thiserror 1.0.69",
4204
+
]
4205
+
4206
+
[[package]]
4207
+
name = "static_assertions"
4208
+
version = "1.1.0"
4209
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4210
+
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
4211
+
4212
+
[[package]]
4213
+
name = "string_cache"
4214
+
version = "0.8.9"
4215
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4216
+
checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f"
4217
+
dependencies = [
4218
+
"new_debug_unreachable",
4219
+
"parking_lot",
4220
+
"phf_shared",
4221
+
"precomputed-hash",
4222
+
"serde",
4223
+
]
4224
+
4225
+
[[package]]
4226
+
name = "string_cache_codegen"
4227
+
version = "0.5.4"
4228
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4229
+
checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0"
4230
+
dependencies = [
4231
+
"phf_generator",
4232
+
"phf_shared",
4233
+
"proc-macro2",
4234
+
"quote",
4235
+
]
4236
+
4237
+
[[package]]
4238
+
name = "stringprep"
4239
+
version = "0.1.5"
4240
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4241
+
checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
4242
+
dependencies = [
4243
+
"unicode-bidi",
4244
+
"unicode-normalization",
4245
+
"unicode-properties",
4246
+
]
4247
+
4248
+
[[package]]
4249
+
name = "strsim"
4250
+
version = "0.11.1"
4251
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4252
+
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
4253
+
4254
+
[[package]]
4255
+
name = "subtle"
4256
+
version = "2.6.1"
4257
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4258
+
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
4259
+
4260
+
[[package]]
4261
+
name = "syn"
4262
+
version = "1.0.109"
4263
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4264
+
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
4265
+
dependencies = [
4266
+
"proc-macro2",
4267
+
"quote",
4268
+
"unicode-ident",
4269
+
]
4270
+
4271
+
[[package]]
4272
+
name = "syn"
4273
+
version = "2.0.111"
4274
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4275
+
checksum = "390cc9a294ab71bdb1aa2e99d13be9c753cd2d7bd6560c77118597410c4d2e87"
4276
+
dependencies = [
4277
+
"proc-macro2",
4278
+
"quote",
4279
+
"unicode-ident",
4280
+
]
4281
+
4282
+
[[package]]
4283
+
name = "sync_wrapper"
4284
+
version = "1.0.2"
4285
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4286
+
checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263"
4287
+
dependencies = [
4288
+
"futures-core",
4289
+
]
4290
+
4291
+
[[package]]
4292
+
name = "synstructure"
4293
+
version = "0.13.2"
4294
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4295
+
checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
4296
+
dependencies = [
4297
+
"proc-macro2",
4298
+
"quote",
4299
+
"syn 2.0.111",
4300
+
]
4301
+
4302
+
[[package]]
4303
+
name = "system-configuration"
4304
+
version = "0.6.1"
4305
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4306
+
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
4307
+
dependencies = [
4308
+
"bitflags",
4309
+
"core-foundation 0.9.4",
4310
+
"system-configuration-sys",
4311
+
]
4312
+
4313
+
[[package]]
4314
+
name = "system-configuration-sys"
4315
+
version = "0.6.0"
4316
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4317
+
checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4"
4318
+
dependencies = [
4319
+
"core-foundation-sys",
4320
+
"libc",
4321
+
]
4322
+
4323
+
[[package]]
4324
+
name = "tagptr"
4325
+
version = "0.2.0"
4326
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4327
+
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
4328
+
4329
+
[[package]]
4330
+
name = "tempfile"
4331
+
version = "3.23.0"
4332
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4333
+
checksum = "2d31c77bdf42a745371d260a26ca7163f1e0924b64afa0b688e61b5a9fa02f16"
4334
+
dependencies = [
4335
+
"fastrand",
4336
+
"getrandom 0.3.4",
4337
+
"once_cell",
4338
+
"rustix",
4339
+
"windows-sys 0.61.2",
4340
+
]
4341
+
4342
+
[[package]]
4343
+
name = "tendril"
4344
+
version = "0.4.3"
4345
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4346
+
checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0"
4347
+
dependencies = [
4348
+
"futf",
4349
+
"mac",
4350
+
"utf-8",
4351
+
]
4352
+
4353
+
[[package]]
4354
+
name = "thiserror"
4355
+
version = "1.0.69"
4356
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4357
+
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
4358
+
dependencies = [
4359
+
"thiserror-impl 1.0.69",
4360
+
]
4361
+
4362
+
[[package]]
4363
+
name = "thiserror"
4364
+
version = "2.0.17"
4365
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4366
+
checksum = "f63587ca0f12b72a0600bcba1d40081f830876000bb46dd2337a3051618f4fc8"
4367
+
dependencies = [
4368
+
"thiserror-impl 2.0.17",
4369
+
]
4370
+
4371
+
[[package]]
4372
+
name = "thiserror-impl"
4373
+
version = "1.0.69"
4374
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4375
+
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
4376
+
dependencies = [
4377
+
"proc-macro2",
4378
+
"quote",
4379
+
"syn 2.0.111",
4380
+
]
4381
+
4382
+
[[package]]
4383
+
name = "thiserror-impl"
4384
+
version = "2.0.17"
4385
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4386
+
checksum = "3ff15c8ecd7de3849db632e14d18d2571fa09dfc5ed93479bc4485c7a517c913"
4387
+
dependencies = [
4388
+
"proc-macro2",
4389
+
"quote",
4390
+
"syn 2.0.111",
4391
+
]
4392
+
4393
+
[[package]]
4394
+
name = "thread_local"
4395
+
version = "1.1.9"
4396
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4397
+
checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
4398
+
dependencies = [
4399
+
"cfg-if",
4400
+
]
4401
+
4402
+
[[package]]
4403
+
name = "threadpool"
4404
+
version = "1.8.1"
4405
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4406
+
checksum = "d050e60b33d41c19108b32cea32164033a9013fe3b46cbd4457559bfbf77afaa"
4407
+
dependencies = [
4408
+
"num_cpus",
4409
+
]
4410
+
4411
+
[[package]]
4412
+
name = "time"
4413
+
version = "0.3.44"
4414
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4415
+
checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d"
4416
+
dependencies = [
4417
+
"deranged",
4418
+
"itoa",
4419
+
"libc",
4420
+
"num-conv",
4421
+
"num_threads",
4422
+
"powerfmt",
4423
+
"serde",
4424
+
"time-core",
4425
+
"time-macros",
4426
+
]
4427
+
4428
+
[[package]]
4429
+
name = "time-core"
4430
+
version = "0.1.6"
4431
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4432
+
checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b"
4433
+
4434
+
[[package]]
4435
+
name = "time-macros"
4436
+
version = "0.2.24"
4437
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4438
+
checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3"
4439
+
dependencies = [
4440
+
"num-conv",
4441
+
"time-core",
4442
+
]
4443
+
4444
+
[[package]]
4445
+
name = "tiny_http"
4446
+
version = "0.12.0"
4447
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4448
+
checksum = "389915df6413a2e74fb181895f933386023c71110878cd0825588928e64cdc82"
4449
+
dependencies = [
4450
+
"ascii",
4451
+
"chunked_transfer",
4452
+
"httpdate",
4453
+
"log",
4454
+
]
4455
+
4456
+
[[package]]
4457
+
name = "tinystr"
4458
+
version = "0.8.2"
4459
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4460
+
checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869"
4461
+
dependencies = [
4462
+
"displaydoc",
4463
+
"zerovec",
4464
+
]
4465
+
4466
+
[[package]]
4467
+
name = "tinyvec"
4468
+
version = "1.10.0"
4469
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4470
+
checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
4471
+
dependencies = [
4472
+
"tinyvec_macros",
4473
+
]
4474
+
4475
+
[[package]]
4476
+
name = "tinyvec_macros"
4477
+
version = "0.1.1"
4478
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4479
+
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
4480
+
4481
+
[[package]]
4482
+
name = "tokio"
4483
+
version = "1.48.0"
4484
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4485
+
checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408"
4486
+
dependencies = [
4487
+
"bytes",
4488
+
"libc",
4489
+
"mio",
4490
+
"pin-project-lite",
4491
+
"socket2 0.6.1",
4492
+
"tokio-macros",
4493
+
"windows-sys 0.61.2",
4494
+
]
4495
+
4496
+
[[package]]
4497
+
name = "tokio-macros"
4498
+
version = "2.6.0"
4499
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4500
+
checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5"
4501
+
dependencies = [
4502
+
"proc-macro2",
4503
+
"quote",
4504
+
"syn 2.0.111",
4505
+
]
4506
+
4507
+
[[package]]
4508
+
name = "tokio-native-tls"
4509
+
version = "0.3.1"
4510
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4511
+
checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2"
4512
+
dependencies = [
4513
+
"native-tls",
4514
+
"tokio",
4515
+
]
4516
+
4517
+
[[package]]
4518
+
name = "tokio-rustls"
4519
+
version = "0.26.4"
4520
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4521
+
checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61"
4522
+
dependencies = [
4523
+
"rustls",
4524
+
"tokio",
4525
+
]
4526
+
4527
+
[[package]]
4528
+
name = "tokio-stream"
4529
+
version = "0.1.17"
4530
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4531
+
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
4532
+
dependencies = [
4533
+
"futures-core",
4534
+
"pin-project-lite",
4535
+
"tokio",
4536
+
]
4537
+
4538
+
[[package]]
4539
+
name = "tokio-util"
4540
+
version = "0.7.17"
4541
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4542
+
checksum = "2efa149fe76073d6e8fd97ef4f4eca7b67f599660115591483572e406e165594"
4543
+
dependencies = [
4544
+
"bytes",
4545
+
"futures-core",
4546
+
"futures-sink",
4547
+
"futures-util",
4548
+
"pin-project-lite",
4549
+
"tokio",
4550
+
]
4551
+
4552
+
[[package]]
4553
+
name = "tower"
4554
+
version = "0.5.2"
4555
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4556
+
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
4557
+
dependencies = [
4558
+
"futures-core",
4559
+
"futures-util",
4560
+
"pin-project-lite",
4561
+
"sync_wrapper",
4562
+
"tokio",
4563
+
"tower-layer",
4564
+
"tower-service",
4565
+
"tracing",
4566
+
]
4567
+
4568
+
[[package]]
4569
+
name = "tower-http"
4570
+
version = "0.6.7"
4571
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4572
+
checksum = "9cf146f99d442e8e68e585f5d798ccd3cad9a7835b917e09728880a862706456"
4573
+
dependencies = [
4574
+
"bitflags",
4575
+
"bytes",
4576
+
"futures-util",
4577
+
"http",
4578
+
"http-body",
4579
+
"iri-string",
4580
+
"pin-project-lite",
4581
+
"tower",
4582
+
"tower-layer",
4583
+
"tower-service",
4584
+
"tracing",
4585
+
]
4586
+
4587
+
[[package]]
4588
+
name = "tower-layer"
4589
+
version = "0.3.3"
4590
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4591
+
checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e"
4592
+
4593
+
[[package]]
4594
+
name = "tower-service"
4595
+
version = "0.3.3"
4596
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4597
+
checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3"
4598
+
4599
+
[[package]]
4600
+
name = "tracing"
4601
+
version = "0.1.43"
4602
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4603
+
checksum = "2d15d90a0b5c19378952d479dc858407149d7bb45a14de0142f6c534b16fc647"
4604
+
dependencies = [
4605
+
"log",
4606
+
"pin-project-lite",
4607
+
"tracing-attributes",
4608
+
"tracing-core",
4609
+
]
4610
+
4611
+
[[package]]
4612
+
name = "tracing-attributes"
4613
+
version = "0.1.31"
4614
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4615
+
checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da"
4616
+
dependencies = [
4617
+
"proc-macro2",
4618
+
"quote",
4619
+
"syn 2.0.111",
4620
+
]
4621
+
4622
+
[[package]]
4623
+
name = "tracing-core"
4624
+
version = "0.1.35"
4625
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4626
+
checksum = "7a04e24fab5c89c6a36eb8558c9656f30d81de51dfa4d3b45f26b21d61fa0a6c"
4627
+
dependencies = [
4628
+
"once_cell",
4629
+
"valuable",
4630
+
]
4631
+
4632
+
[[package]]
4633
+
name = "tracing-log"
4634
+
version = "0.2.0"
4635
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4636
+
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
4637
+
dependencies = [
4638
+
"log",
4639
+
"once_cell",
4640
+
"tracing-core",
4641
+
]
4642
+
4643
+
[[package]]
4644
+
name = "tracing-subscriber"
4645
+
version = "0.3.22"
4646
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4647
+
checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e"
4648
+
dependencies = [
4649
+
"matchers",
4650
+
"nu-ansi-term",
4651
+
"once_cell",
4652
+
"regex-automata",
4653
+
"sharded-slab",
4654
+
"smallvec",
4655
+
"thread_local",
4656
+
"tracing",
4657
+
"tracing-core",
4658
+
"tracing-log",
4659
+
]
4660
+
4661
+
[[package]]
4662
+
name = "trait-variant"
4663
+
version = "0.1.2"
4664
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4665
+
checksum = "70977707304198400eb4835a78f6a9f928bf41bba420deb8fdb175cd965d77a7"
4666
+
dependencies = [
4667
+
"proc-macro2",
4668
+
"quote",
4669
+
"syn 2.0.111",
4670
+
]
4671
+
4672
+
[[package]]
4673
+
name = "triomphe"
4674
+
version = "0.1.15"
4675
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4676
+
checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39"
4677
+
4678
+
[[package]]
4679
+
name = "try-lock"
4680
+
version = "0.2.5"
4681
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4682
+
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
4683
+
4684
+
[[package]]
4685
+
name = "twoway"
4686
+
version = "0.1.8"
4687
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4688
+
checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1"
4689
+
dependencies = [
4690
+
"memchr",
4691
+
]
4692
+
4693
+
[[package]]
4694
+
name = "typenum"
4695
+
version = "1.19.0"
4696
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4697
+
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
4698
+
4699
+
[[package]]
4700
+
name = "unicase"
4701
+
version = "2.8.1"
4702
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4703
+
checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
4704
+
4705
+
[[package]]
4706
+
name = "unicode-bidi"
4707
+
version = "0.3.18"
4708
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4709
+
checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
4710
+
4711
+
[[package]]
4712
+
name = "unicode-ident"
4713
+
version = "1.0.22"
4714
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4715
+
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
4716
+
4717
+
[[package]]
4718
+
name = "unicode-normalization"
4719
+
version = "0.1.25"
4720
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4721
+
checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8"
4722
+
dependencies = [
4723
+
"tinyvec",
4724
+
]
4725
+
4726
+
[[package]]
4727
+
name = "unicode-properties"
4728
+
version = "0.1.4"
4729
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4730
+
checksum = "7df058c713841ad818f1dc5d3fd88063241cc61f49f5fbea4b951e8cf5a8d71d"
4731
+
4732
+
[[package]]
4733
+
name = "unicode-segmentation"
4734
+
version = "1.12.0"
4735
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4736
+
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
4737
+
4738
+
[[package]]
4739
+
name = "unicode-width"
4740
+
version = "0.1.14"
4741
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4742
+
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
4743
+
4744
+
[[package]]
4745
+
name = "unicode-xid"
4746
+
version = "0.2.6"
4747
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4748
+
checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853"
4749
+
4750
+
[[package]]
4751
+
name = "unsigned-varint"
4752
+
version = "0.7.2"
4753
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4754
+
checksum = "6889a77d49f1f013504cec6bf97a2c730394adedaeb1deb5ea08949a50541105"
4755
+
4756
+
[[package]]
4757
+
name = "unsigned-varint"
4758
+
version = "0.8.0"
4759
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4760
+
checksum = "eb066959b24b5196ae73cb057f45598450d2c5f71460e98c49b738086eff9c06"
4761
+
4762
+
[[package]]
4763
+
name = "untrusted"
4764
+
version = "0.9.0"
4765
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4766
+
checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
4767
+
4768
+
[[package]]
4769
+
name = "url"
4770
+
version = "2.5.7"
4771
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4772
+
checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
4773
+
dependencies = [
4774
+
"form_urlencoded",
4775
+
"idna",
4776
+
"percent-encoding",
4777
+
"serde",
4778
+
]
4779
+
4780
+
[[package]]
4781
+
name = "urlencoding"
4782
+
version = "2.1.3"
4783
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4784
+
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
4785
+
4786
+
[[package]]
4787
+
name = "utf-8"
4788
+
version = "0.7.6"
4789
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4790
+
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
4791
+
4792
+
[[package]]
4793
+
name = "utf8_iter"
4794
+
version = "1.0.4"
4795
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4796
+
checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
4797
+
4798
+
[[package]]
4799
+
name = "uuid"
4800
+
version = "1.19.0"
4801
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4802
+
checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
4803
+
dependencies = [
4804
+
"getrandom 0.3.4",
4805
+
"js-sys",
4806
+
"rand 0.9.2",
4807
+
"wasm-bindgen",
4808
+
]
4809
+
4810
+
[[package]]
4811
+
name = "valuable"
4812
+
version = "0.1.1"
4813
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4814
+
checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65"
4815
+
4816
+
[[package]]
4817
+
name = "vcpkg"
4818
+
version = "0.2.15"
4819
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4820
+
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
4821
+
4822
+
[[package]]
4823
+
name = "version_check"
4824
+
version = "0.9.5"
4825
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4826
+
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
4827
+
4828
+
[[package]]
4829
+
name = "walkdir"
4830
+
version = "2.5.0"
4831
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4832
+
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
4833
+
dependencies = [
4834
+
"same-file",
4835
+
"winapi-util",
4836
+
]
4837
+
4838
+
[[package]]
4839
+
name = "want"
4840
+
version = "0.3.1"
4841
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4842
+
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
4843
+
dependencies = [
4844
+
"try-lock",
4845
+
]
4846
+
4847
+
[[package]]
4848
+
name = "wasi"
4849
+
version = "0.11.1+wasi-snapshot-preview1"
4850
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4851
+
checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
4852
+
4853
+
[[package]]
4854
+
name = "wasip2"
4855
+
version = "1.0.1+wasi-0.2.4"
4856
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4857
+
checksum = "0562428422c63773dad2c345a1882263bbf4d65cf3f42e90921f787ef5ad58e7"
4858
+
dependencies = [
4859
+
"wit-bindgen",
4860
+
]
4861
+
4862
+
[[package]]
4863
+
name = "wasite"
4864
+
version = "0.1.0"
4865
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4866
+
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
4867
+
4868
+
[[package]]
4869
+
name = "wasm-bindgen"
4870
+
version = "0.2.106"
4871
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4872
+
checksum = "0d759f433fa64a2d763d1340820e46e111a7a5ab75f993d1852d70b03dbb80fd"
4873
+
dependencies = [
4874
+
"cfg-if",
4875
+
"once_cell",
4876
+
"rustversion",
4877
+
"wasm-bindgen-macro",
4878
+
"wasm-bindgen-shared",
4879
+
]
4880
+
4881
+
[[package]]
4882
+
name = "wasm-bindgen-futures"
4883
+
version = "0.4.56"
4884
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4885
+
checksum = "836d9622d604feee9e5de25ac10e3ea5f2d65b41eac0d9ce72eb5deae707ce7c"
4886
+
dependencies = [
4887
+
"cfg-if",
4888
+
"js-sys",
4889
+
"once_cell",
4890
+
"wasm-bindgen",
4891
+
"web-sys",
4892
+
]
4893
+
4894
+
[[package]]
4895
+
name = "wasm-bindgen-macro"
4896
+
version = "0.2.106"
4897
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4898
+
checksum = "48cb0d2638f8baedbc542ed444afc0644a29166f1595371af4fecf8ce1e7eeb3"
4899
+
dependencies = [
4900
+
"quote",
4901
+
"wasm-bindgen-macro-support",
4902
+
]
4903
+
4904
+
[[package]]
4905
+
name = "wasm-bindgen-macro-support"
4906
+
version = "0.2.106"
4907
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4908
+
checksum = "cefb59d5cd5f92d9dcf80e4683949f15ca4b511f4ac0a6e14d4e1ac60c6ecd40"
4909
+
dependencies = [
4910
+
"bumpalo",
4911
+
"proc-macro2",
4912
+
"quote",
4913
+
"syn 2.0.111",
4914
+
"wasm-bindgen-shared",
4915
+
]
4916
+
4917
+
[[package]]
4918
+
name = "wasm-bindgen-shared"
4919
+
version = "0.2.106"
4920
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4921
+
checksum = "cbc538057e648b67f72a982e708d485b2efa771e1ac05fec311f9f63e5800db4"
4922
+
dependencies = [
4923
+
"unicode-ident",
4924
+
]
4925
+
4926
+
[[package]]
4927
+
name = "wasm-streams"
4928
+
version = "0.4.2"
4929
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4930
+
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
4931
+
dependencies = [
4932
+
"futures-util",
4933
+
"js-sys",
4934
+
"wasm-bindgen",
4935
+
"wasm-bindgen-futures",
4936
+
"web-sys",
4937
+
]
4938
+
4939
+
[[package]]
4940
+
name = "web-sys"
4941
+
version = "0.3.83"
4942
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4943
+
checksum = "9b32828d774c412041098d182a8b38b16ea816958e07cf40eec2bc080ae137ac"
4944
+
dependencies = [
4945
+
"js-sys",
4946
+
"wasm-bindgen",
4947
+
]
4948
+
4949
+
[[package]]
4950
+
name = "web-time"
4951
+
version = "1.1.0"
4952
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4953
+
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
4954
+
dependencies = [
4955
+
"js-sys",
4956
+
"wasm-bindgen",
4957
+
]
4958
+
4959
+
[[package]]
4960
+
name = "webbrowser"
4961
+
version = "1.0.6"
4962
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4963
+
checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97"
4964
+
dependencies = [
4965
+
"core-foundation 0.10.1",
4966
+
"jni",
4967
+
"log",
4968
+
"ndk-context",
4969
+
"objc2",
4970
+
"objc2-foundation",
4971
+
"url",
4972
+
"web-sys",
4973
+
]
4974
+
4975
+
[[package]]
4976
+
name = "webpage"
4977
+
version = "2.0.1"
4978
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4979
+
checksum = "70862efc041d46e6bbaa82bb9c34ae0596d090e86cbd14bd9e93b36ee6802eac"
4980
+
dependencies = [
4981
+
"html5ever",
4982
+
"markup5ever_rcdom",
4983
+
"serde_json",
4984
+
"url",
4985
+
]
4986
+
4987
+
[[package]]
4988
+
name = "webpki-roots"
4989
+
version = "0.26.11"
4990
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4991
+
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
4992
+
dependencies = [
4993
+
"webpki-roots 1.0.4",
4994
+
]
4995
+
4996
+
[[package]]
4997
+
name = "webpki-roots"
4998
+
version = "1.0.4"
4999
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5000
+
checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e"
5001
+
dependencies = [
5002
+
"rustls-pki-types",
5003
+
]
5004
+
5005
+
[[package]]
5006
+
name = "whoami"
5007
+
version = "1.6.1"
5008
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5009
+
checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
5010
+
dependencies = [
5011
+
"libredox",
5012
+
"wasite",
5013
+
]
5014
+
5015
+
[[package]]
5016
+
name = "widestring"
5017
+
version = "1.2.1"
5018
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5019
+
checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471"
5020
+
5021
+
[[package]]
5022
+
name = "winapi-util"
5023
+
version = "0.1.11"
5024
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5025
+
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
5026
+
dependencies = [
5027
+
"windows-sys 0.61.2",
5028
+
]
5029
+
5030
+
[[package]]
5031
+
name = "windows"
5032
+
version = "0.61.3"
5033
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5034
+
checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893"
5035
+
dependencies = [
5036
+
"windows-collections",
5037
+
"windows-core 0.61.2",
5038
+
"windows-future",
5039
+
"windows-link 0.1.3",
5040
+
"windows-numerics",
5041
+
]
5042
+
5043
+
[[package]]
5044
+
name = "windows-collections"
5045
+
version = "0.2.0"
5046
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5047
+
checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8"
5048
+
dependencies = [
5049
+
"windows-core 0.61.2",
5050
+
]
5051
+
5052
+
[[package]]
5053
+
name = "windows-core"
5054
+
version = "0.61.2"
5055
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5056
+
checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
5057
+
dependencies = [
5058
+
"windows-implement",
5059
+
"windows-interface",
5060
+
"windows-link 0.1.3",
5061
+
"windows-result 0.3.4",
5062
+
"windows-strings 0.4.2",
5063
+
]
5064
+
5065
+
[[package]]
5066
+
name = "windows-core"
5067
+
version = "0.62.2"
5068
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5069
+
checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
5070
+
dependencies = [
5071
+
"windows-implement",
5072
+
"windows-interface",
5073
+
"windows-link 0.2.1",
5074
+
"windows-result 0.4.1",
5075
+
"windows-strings 0.5.1",
5076
+
]
5077
+
5078
+
[[package]]
5079
+
name = "windows-future"
5080
+
version = "0.2.1"
5081
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5082
+
checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e"
5083
+
dependencies = [
5084
+
"windows-core 0.61.2",
5085
+
"windows-link 0.1.3",
5086
+
"windows-threading",
5087
+
]
5088
+
5089
+
[[package]]
5090
+
name = "windows-implement"
5091
+
version = "0.60.2"
5092
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5093
+
checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
5094
+
dependencies = [
5095
+
"proc-macro2",
5096
+
"quote",
5097
+
"syn 2.0.111",
5098
+
]
5099
+
5100
+
[[package]]
5101
+
name = "windows-interface"
5102
+
version = "0.59.3"
5103
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5104
+
checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
5105
+
dependencies = [
5106
+
"proc-macro2",
5107
+
"quote",
5108
+
"syn 2.0.111",
5109
+
]
5110
+
5111
+
[[package]]
5112
+
name = "windows-link"
5113
+
version = "0.1.3"
5114
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5115
+
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
5116
+
5117
+
[[package]]
5118
+
name = "windows-link"
5119
+
version = "0.2.1"
5120
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5121
+
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
5122
+
5123
+
[[package]]
5124
+
name = "windows-numerics"
5125
+
version = "0.2.0"
5126
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5127
+
checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1"
5128
+
dependencies = [
5129
+
"windows-core 0.61.2",
5130
+
"windows-link 0.1.3",
5131
+
]
5132
+
5133
+
[[package]]
5134
+
name = "windows-registry"
5135
+
version = "0.6.1"
5136
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5137
+
checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720"
5138
+
dependencies = [
5139
+
"windows-link 0.2.1",
5140
+
"windows-result 0.4.1",
5141
+
"windows-strings 0.5.1",
5142
+
]
5143
+
5144
+
[[package]]
5145
+
name = "windows-result"
5146
+
version = "0.3.4"
5147
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5148
+
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
5149
+
dependencies = [
5150
+
"windows-link 0.1.3",
5151
+
]
5152
+
5153
+
[[package]]
5154
+
name = "windows-result"
5155
+
version = "0.4.1"
5156
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5157
+
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
5158
+
dependencies = [
5159
+
"windows-link 0.2.1",
5160
+
]
5161
+
5162
+
[[package]]
5163
+
name = "windows-strings"
5164
+
version = "0.4.2"
5165
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5166
+
checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
5167
+
dependencies = [
5168
+
"windows-link 0.1.3",
5169
+
]
5170
+
5171
+
[[package]]
5172
+
name = "windows-strings"
5173
+
version = "0.5.1"
5174
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5175
+
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
5176
+
dependencies = [
5177
+
"windows-link 0.2.1",
5178
+
]
5179
+
5180
+
[[package]]
5181
+
name = "windows-sys"
5182
+
version = "0.45.0"
5183
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5184
+
checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
5185
+
dependencies = [
5186
+
"windows-targets 0.42.2",
5187
+
]
5188
+
5189
+
[[package]]
5190
+
name = "windows-sys"
5191
+
version = "0.48.0"
5192
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5193
+
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
5194
+
dependencies = [
5195
+
"windows-targets 0.48.5",
5196
+
]
5197
+
5198
+
[[package]]
5199
+
name = "windows-sys"
5200
+
version = "0.52.0"
5201
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5202
+
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
5203
+
dependencies = [
5204
+
"windows-targets 0.52.6",
5205
+
]
5206
+
5207
+
[[package]]
5208
+
name = "windows-sys"
5209
+
version = "0.60.2"
5210
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5211
+
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
5212
+
dependencies = [
5213
+
"windows-targets 0.53.5",
5214
+
]
5215
+
5216
+
[[package]]
5217
+
name = "windows-sys"
5218
+
version = "0.61.2"
5219
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5220
+
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
5221
+
dependencies = [
5222
+
"windows-link 0.2.1",
5223
+
]
5224
+
5225
+
[[package]]
5226
+
name = "windows-targets"
5227
+
version = "0.42.2"
5228
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5229
+
checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
5230
+
dependencies = [
5231
+
"windows_aarch64_gnullvm 0.42.2",
5232
+
"windows_aarch64_msvc 0.42.2",
5233
+
"windows_i686_gnu 0.42.2",
5234
+
"windows_i686_msvc 0.42.2",
5235
+
"windows_x86_64_gnu 0.42.2",
5236
+
"windows_x86_64_gnullvm 0.42.2",
5237
+
"windows_x86_64_msvc 0.42.2",
5238
+
]
5239
+
5240
+
[[package]]
5241
+
name = "windows-targets"
5242
+
version = "0.48.5"
5243
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5244
+
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
5245
+
dependencies = [
5246
+
"windows_aarch64_gnullvm 0.48.5",
5247
+
"windows_aarch64_msvc 0.48.5",
5248
+
"windows_i686_gnu 0.48.5",
5249
+
"windows_i686_msvc 0.48.5",
5250
+
"windows_x86_64_gnu 0.48.5",
5251
+
"windows_x86_64_gnullvm 0.48.5",
5252
+
"windows_x86_64_msvc 0.48.5",
5253
+
]
5254
+
5255
+
[[package]]
5256
+
name = "windows-targets"
5257
+
version = "0.52.6"
5258
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5259
+
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
5260
+
dependencies = [
5261
+
"windows_aarch64_gnullvm 0.52.6",
5262
+
"windows_aarch64_msvc 0.52.6",
5263
+
"windows_i686_gnu 0.52.6",
5264
+
"windows_i686_gnullvm 0.52.6",
5265
+
"windows_i686_msvc 0.52.6",
5266
+
"windows_x86_64_gnu 0.52.6",
5267
+
"windows_x86_64_gnullvm 0.52.6",
5268
+
"windows_x86_64_msvc 0.52.6",
5269
+
]
5270
+
5271
+
[[package]]
5272
+
name = "windows-targets"
5273
+
version = "0.53.5"
5274
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5275
+
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
5276
+
dependencies = [
5277
+
"windows-link 0.2.1",
5278
+
"windows_aarch64_gnullvm 0.53.1",
5279
+
"windows_aarch64_msvc 0.53.1",
5280
+
"windows_i686_gnu 0.53.1",
5281
+
"windows_i686_gnullvm 0.53.1",
5282
+
"windows_i686_msvc 0.53.1",
5283
+
"windows_x86_64_gnu 0.53.1",
5284
+
"windows_x86_64_gnullvm 0.53.1",
5285
+
"windows_x86_64_msvc 0.53.1",
5286
+
]
5287
+
5288
+
[[package]]
5289
+
name = "windows-threading"
5290
+
version = "0.1.0"
5291
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5292
+
checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6"
5293
+
dependencies = [
5294
+
"windows-link 0.1.3",
5295
+
]
5296
+
5297
+
[[package]]
5298
+
name = "windows_aarch64_gnullvm"
5299
+
version = "0.42.2"
5300
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5301
+
checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
5302
+
5303
+
[[package]]
5304
+
name = "windows_aarch64_gnullvm"
5305
+
version = "0.48.5"
5306
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5307
+
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
5308
+
5309
+
[[package]]
5310
+
name = "windows_aarch64_gnullvm"
5311
+
version = "0.52.6"
5312
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5313
+
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
5314
+
5315
+
[[package]]
5316
+
name = "windows_aarch64_gnullvm"
5317
+
version = "0.53.1"
5318
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5319
+
checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53"
5320
+
5321
+
[[package]]
5322
+
name = "windows_aarch64_msvc"
5323
+
version = "0.42.2"
5324
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5325
+
checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
5326
+
5327
+
[[package]]
5328
+
name = "windows_aarch64_msvc"
5329
+
version = "0.48.5"
5330
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5331
+
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
5332
+
5333
+
[[package]]
5334
+
name = "windows_aarch64_msvc"
5335
+
version = "0.52.6"
5336
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5337
+
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
5338
+
5339
+
[[package]]
5340
+
name = "windows_aarch64_msvc"
5341
+
version = "0.53.1"
5342
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5343
+
checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006"
5344
+
5345
+
[[package]]
5346
+
name = "windows_i686_gnu"
5347
+
version = "0.42.2"
5348
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5349
+
checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
5350
+
5351
+
[[package]]
5352
+
name = "windows_i686_gnu"
5353
+
version = "0.48.5"
5354
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5355
+
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
5356
+
5357
+
[[package]]
5358
+
name = "windows_i686_gnu"
5359
+
version = "0.52.6"
5360
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5361
+
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
5362
+
5363
+
[[package]]
5364
+
name = "windows_i686_gnu"
5365
+
version = "0.53.1"
5366
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5367
+
checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3"
5368
+
5369
+
[[package]]
5370
+
name = "windows_i686_gnullvm"
5371
+
version = "0.52.6"
5372
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5373
+
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
5374
+
5375
+
[[package]]
5376
+
name = "windows_i686_gnullvm"
5377
+
version = "0.53.1"
5378
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5379
+
checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c"
5380
+
5381
+
[[package]]
5382
+
name = "windows_i686_msvc"
5383
+
version = "0.42.2"
5384
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5385
+
checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
5386
+
5387
+
[[package]]
5388
+
name = "windows_i686_msvc"
5389
+
version = "0.48.5"
5390
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5391
+
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
5392
+
5393
+
[[package]]
5394
+
name = "windows_i686_msvc"
5395
+
version = "0.52.6"
5396
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5397
+
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
5398
+
5399
+
[[package]]
5400
+
name = "windows_i686_msvc"
5401
+
version = "0.53.1"
5402
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5403
+
checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2"
5404
+
5405
+
[[package]]
5406
+
name = "windows_x86_64_gnu"
5407
+
version = "0.42.2"
5408
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5409
+
checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
5410
+
5411
+
[[package]]
5412
+
name = "windows_x86_64_gnu"
5413
+
version = "0.48.5"
5414
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5415
+
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
5416
+
5417
+
[[package]]
5418
+
name = "windows_x86_64_gnu"
5419
+
version = "0.52.6"
5420
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5421
+
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
5422
+
5423
+
[[package]]
5424
+
name = "windows_x86_64_gnu"
5425
+
version = "0.53.1"
5426
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5427
+
checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499"
5428
+
5429
+
[[package]]
5430
+
name = "windows_x86_64_gnullvm"
5431
+
version = "0.42.2"
5432
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5433
+
checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
5434
+
5435
+
[[package]]
5436
+
name = "windows_x86_64_gnullvm"
5437
+
version = "0.48.5"
5438
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5439
+
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
5440
+
5441
+
[[package]]
5442
+
name = "windows_x86_64_gnullvm"
5443
+
version = "0.52.6"
5444
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5445
+
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
5446
+
5447
+
[[package]]
5448
+
name = "windows_x86_64_gnullvm"
5449
+
version = "0.53.1"
5450
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5451
+
checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1"
5452
+
5453
+
[[package]]
5454
+
name = "windows_x86_64_msvc"
5455
+
version = "0.42.2"
5456
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5457
+
checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
5458
+
5459
+
[[package]]
5460
+
name = "windows_x86_64_msvc"
5461
+
version = "0.48.5"
5462
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5463
+
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
5464
+
5465
+
[[package]]
5466
+
name = "windows_x86_64_msvc"
5467
+
version = "0.52.6"
5468
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5469
+
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
5470
+
5471
+
[[package]]
5472
+
name = "windows_x86_64_msvc"
5473
+
version = "0.53.1"
5474
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5475
+
checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650"
5476
+
5477
+
[[package]]
5478
+
name = "winreg"
5479
+
version = "0.50.0"
5480
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5481
+
checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1"
5482
+
dependencies = [
5483
+
"cfg-if",
5484
+
"windows-sys 0.48.0",
5485
+
]
5486
+
5487
+
[[package]]
5488
+
name = "wit-bindgen"
5489
+
version = "0.46.0"
5490
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5491
+
checksum = "f17a85883d4e6d00e8a97c586de764dabcc06133f7f1d55dce5cdc070ad7fe59"
5492
+
5493
+
[[package]]
5494
+
name = "writeable"
5495
+
version = "0.6.2"
5496
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5497
+
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
5498
+
5499
+
[[package]]
5500
+
name = "xml5ever"
5501
+
version = "0.18.1"
5502
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5503
+
checksum = "9bbb26405d8e919bc1547a5aa9abc95cbfa438f04844f5fdd9dc7596b748bf69"
5504
+
dependencies = [
5505
+
"log",
5506
+
"mac",
5507
+
"markup5ever",
5508
+
]
5509
+
5510
+
[[package]]
5511
+
name = "yansi"
5512
+
version = "1.0.1"
5513
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5514
+
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
5515
+
5516
+
[[package]]
5517
+
name = "yoke"
5518
+
version = "0.8.1"
5519
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5520
+
checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954"
5521
+
dependencies = [
5522
+
"stable_deref_trait",
5523
+
"yoke-derive",
5524
+
"zerofrom",
5525
+
]
5526
+
5527
+
[[package]]
5528
+
name = "yoke-derive"
5529
+
version = "0.8.1"
5530
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5531
+
checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d"
5532
+
dependencies = [
5533
+
"proc-macro2",
5534
+
"quote",
5535
+
"syn 2.0.111",
5536
+
"synstructure",
5537
+
]
5538
+
5539
+
[[package]]
5540
+
name = "zerocopy"
5541
+
version = "0.8.31"
5542
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5543
+
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
5544
+
dependencies = [
5545
+
"zerocopy-derive",
5546
+
]
5547
+
5548
+
[[package]]
5549
+
name = "zerocopy-derive"
5550
+
version = "0.8.31"
5551
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5552
+
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
5553
+
dependencies = [
5554
+
"proc-macro2",
5555
+
"quote",
5556
+
"syn 2.0.111",
5557
+
]
5558
+
5559
+
[[package]]
5560
+
name = "zerofrom"
5561
+
version = "0.1.6"
5562
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5563
+
checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
5564
+
dependencies = [
5565
+
"zerofrom-derive",
5566
+
]
5567
+
5568
+
[[package]]
5569
+
name = "zerofrom-derive"
5570
+
version = "0.1.6"
5571
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5572
+
checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
5573
+
dependencies = [
5574
+
"proc-macro2",
5575
+
"quote",
5576
+
"syn 2.0.111",
5577
+
"synstructure",
5578
+
]
5579
+
5580
+
[[package]]
5581
+
name = "zeroize"
5582
+
version = "1.8.2"
5583
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5584
+
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
5585
+
dependencies = [
5586
+
"serde",
5587
+
]
5588
+
5589
+
[[package]]
5590
+
name = "zerotrie"
5591
+
version = "0.2.3"
5592
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5593
+
checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851"
5594
+
dependencies = [
5595
+
"displaydoc",
5596
+
"yoke",
5597
+
"zerofrom",
5598
+
]
5599
+
5600
+
[[package]]
5601
+
name = "zerovec"
5602
+
version = "0.11.5"
5603
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5604
+
checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002"
5605
+
dependencies = [
5606
+
"yoke",
5607
+
"zerofrom",
5608
+
"zerovec-derive",
5609
+
]
5610
+
5611
+
[[package]]
5612
+
name = "zerovec-derive"
5613
+
version = "0.11.2"
5614
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5615
+
checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3"
5616
+
dependencies = [
5617
+
"proc-macro2",
5618
+
"quote",
5619
+
"syn 2.0.111",
5620
+
]
+28
Cargo.toml
+28
Cargo.toml
···
···
1
+
[package]
2
+
name = "bspds"
3
+
version = "0.1.0"
4
+
edition = "2024"
5
+
6
+
[dependencies]
7
+
anyhow = "1.0.100"
8
+
axum = "0.8.7"
9
+
bcrypt = "0.17.1"
10
+
bytes = "1.11.0"
11
+
chrono = { version = "0.4.42", features = ["serde"] }
12
+
cid = "0.11.1"
13
+
dotenvy = "0.15.7"
14
+
jacquard = "0.9.3"
15
+
jacquard-axum = "0.9.2"
16
+
jacquard-repo = "0.9.2"
17
+
jsonwebtoken = { version = "10.2.0", features = ["rust_crypto"] }
18
+
multihash = "0.19.3"
19
+
reqwest = { version = "0.12.24", features = ["json"] }
20
+
serde = { version = "1.0.228", features = ["derive"] }
21
+
serde_ipld_dagcbor = "0.6.4"
22
+
serde_json = "1.0.145"
23
+
sha2 = "0.10.9"
24
+
sqlx = { version = "0.8.6", features = ["runtime-tokio-rustls", "postgres", "uuid", "chrono", "json"] }
25
+
tokio = { version = "1.48.0", features = ["macros", "rt-multi-thread", "time"] }
26
+
tracing = "0.1.43"
27
+
tracing-subscriber = "0.3.22"
28
+
uuid = { version = "1.19.0", features = ["v4", "fast-rng"] }
+108
TODO.md
+108
TODO.md
···
···
1
+
# Implementation TODOs
2
+
3
+
Lewis' special big boy todofile
4
+
5
+
## 1. Server Infrastructure & Health
6
+
- [x] Health Check
7
+
- [x] Implement `GET /health` endpoint (returns "OK").
8
+
- [x] Server Description
9
+
- [x] Implement `com.atproto.server.describeServer` (returns available user domains).
10
+
11
+
## 2. Authentication & Account Management (`com.atproto.server`)
12
+
- [x] Account Creation
13
+
- [x] Implement `com.atproto.server.createAccount`.
14
+
- [x] Validate handle format (reject invalid characters).
15
+
- [x] Create DID for new user.
16
+
- [x] Initialize user repository.
17
+
- [x] Return access JWT and DID.
18
+
- [x] MST stuff I think...
19
+
20
+
- [x] Session Management
21
+
- [x] Implement `com.atproto.server.createSession` (Login).
22
+
- [x] Validate identifier (handle/email) and password.
23
+
- [x] Return access JWT, refresh JWT, and DID.
24
+
- [x] Implement `com.atproto.server.getSession`.
25
+
- [x] Verify JWT validity.
26
+
- [x] Implement `com.atproto.server.refreshSession`.
27
+
- [x] Implement `com.atproto.server.deleteSession` (Logout).
28
+
- [x] Invalidate current session/token.
29
+
30
+
## 3. Repository Operations (`com.atproto.repo`)
31
+
- [ ] Record CRUD
32
+
- [ ] Implement `com.atproto.repo.createRecord`.
33
+
- [ ] Generate `rkey` if not provided.
34
+
- [ ] Validate schema against Lexicon.
35
+
- [ ] Handle `swapCommit` for optimistic locking.
36
+
- [ ] Implement `com.atproto.repo.putRecord`.
37
+
- [ ] Handle create vs update logic.
38
+
- [ ] Validate `repo` matches authenticated user.
39
+
- [ ] Validate record schema (e.g., missing required fields).
40
+
- [ ] Implement `com.atproto.repo.getRecord`.
41
+
- [ ] Handle missing params (400 Bad Request).
42
+
- [ ] Handle non-existent record (404 Not Found).
43
+
- [ ] Implement `com.atproto.repo.deleteRecord`.
44
+
- [ ] Implement `com.atproto.repo.listRecords`.
45
+
- [ ] Support pagination (`limit`, `cursor`).
46
+
- [ ] Blob Management
47
+
- [ ] Implement `com.atproto.repo.uploadBlob`.
48
+
- [ ] Enforce authentication.
49
+
- [ ] Validate MIME types (reject unsupported).
50
+
- [ ] Return blob reference (`$link`).
51
+
- [ ] Repo Meta
52
+
- [ ] Implement `com.atproto.repo.describeRepo`.
53
+
54
+
## 4. Actor & Profile (`app.bsky.actor`)
55
+
- [ ] Profile Management
56
+
- [ ] Implement `app.bsky.actor.getProfile`.
57
+
- [ ] Resolve handle to DID.
58
+
- [ ] Return profile record data.
59
+
- [ ] Discovery
60
+
- [ ] Implement `app.bsky.actor.searchActors`.
61
+
62
+
## 5. Feed & Timeline (`app.bsky.feed`)
63
+
- [ ] Feed Retrieval
64
+
- [ ] Implement `app.bsky.feed.getTimeline`.
65
+
- [ ] Implement `app.bsky.feed.getAuthorFeed`.
66
+
- [ ] Filter by actor.
67
+
- [ ] Respect mutes (if viewer is authenticated).
68
+
- [ ] Implement `app.bsky.feed.getPostThread`.
69
+
- [ ] Construct thread tree (parents, replies).
70
+
- [ ] Handle deleted posts (return `notFoundPost` view).
71
+
- [ ] Record Types
72
+
- [ ] Support `app.bsky.feed.post` record type.
73
+
- [ ] Support `app.bsky.feed.like` record type.
74
+
- [ ] Support `app.bsky.embed.images` in posts.
75
+
76
+
## 6. Social Graph (`app.bsky.graph`)
77
+
- [ ] Relationships
78
+
- [ ] Implement `app.bsky.graph.getFollows`.
79
+
- [ ] Implement `app.bsky.graph.getFollowers`.
80
+
- [ ] Implement `app.bsky.graph.getMutes`.
81
+
- [ ] Implement `app.bsky.graph.getBlocks`.
82
+
- [ ] Record Types
83
+
- [ ] Support `app.bsky.graph.follow` record type.
84
+
- [ ] Support `app.bsky.graph.mute` record type.
85
+
86
+
## 7. Notifications (`app.bsky.notification`)
87
+
- [ ] Notification Management
88
+
- [ ] Implement `app.bsky.notification.listNotifications`.
89
+
- [ ] Aggregate notifications (likes, follows, replies).
90
+
- [ ] Implement `app.bsky.notification.getUnreadCount`.
91
+
- [ ] Track read state.
92
+
- [ ] Reset count on list/read.
93
+
94
+
## 8. Identity (`com.atproto.identity`)
95
+
- [ ] Resolution
96
+
- [ ] Implement `com.atproto.identity.resolveHandle`.
97
+
98
+
## 9. Sync & Federation (`com.atproto.sync`)
99
+
- [ ] Data Export
100
+
- [ ] Implement `com.atproto.sync.getRepo` (Export CAR file).
101
+
- [ ] Implement `com.atproto.sync.getBlocks`.
102
+
103
+
## 10. General Requirements
104
+
- [ ] Validation
105
+
- [ ] Ensure all endpoints validate input parameters.
106
+
- [ ] Ensure proper error codes (400, 401, 404, 409).
107
+
- [ ] Concurrency
108
+
- [ ] Ensure thread safety for repo updates.
+50
docker-compose.yaml
+50
docker-compose.yaml
···
···
1
+
services:
2
+
app:
3
+
build:
4
+
context: .
5
+
dockerfile: Dockerfile
6
+
image: bspds
7
+
ports:
8
+
- "3000:3000"
9
+
environment:
10
+
SERVER_HOST: 0.0.0.0
11
+
SERVER_PORT: 3000
12
+
DATABASE_URL: postgres://postgres:postgres@db:5432/pds
13
+
OBJECT_STORAGE_ENDPOINT: http://objsto:9000
14
+
OBJECT_STORAGE_REGION: us-east-1
15
+
OBJECT_STORAGE_BUCKET: pds-blobs
16
+
OBJECT_STORAGE_ACCESS_KEY: minioadmin
17
+
OBJECT_STORAGE_SECRET_KEY: minioadmin
18
+
OBJECT_STORAGE_FORCE_PATH_STYLE: "true"
19
+
JWT_SECRET: your-super-secret-jwt-key-please-change-me
20
+
PDS_HOSTNAME: localhost:3000
21
+
depends_on:
22
+
- db
23
+
- objsto
24
+
25
+
db:
26
+
image: postgres:latest
27
+
environment:
28
+
POSTGRES_USER: postgres
29
+
POSTGRES_PASSWORD: postgres
30
+
POSTGRES_DB: pds
31
+
ports:
32
+
- "5432:5432"
33
+
volumes:
34
+
- postgres_data:/var/lib/postgresql
35
+
36
+
objsto:
37
+
image: minio/minio
38
+
ports:
39
+
- "9000:9000"
40
+
- "9001:9001"
41
+
environment:
42
+
MINIO_ROOT_USER: minioadmin
43
+
MINIO_ROOT_PASSWORD: minioadmin
44
+
volumes:
45
+
- minio_data:/data
46
+
command: server /data --console-address ":9001"
47
+
48
+
volumes:
49
+
postgres_data:
50
+
minio_data:
+80
migrations/202512211400_initial_tables.sql
+80
migrations/202512211400_initial_tables.sql
···
···
1
+
-- A very basic schema to get started.
2
+
-- TODO: PRODUCTIONIZE BABY
3
+
4
+
CREATE TABLE IF NOT EXISTS users (
5
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
6
+
handle TEXT NOT NULL UNIQUE,
7
+
email TEXT NOT NULL UNIQUE,
8
+
did TEXT NOT NULL UNIQUE,
9
+
password_hash TEXT NOT NULL,
10
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
11
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
12
+
);
13
+
14
+
CREATE TABLE IF NOT EXISTS invite_codes (
15
+
code TEXT PRIMARY KEY,
16
+
available_uses INT NOT NULL DEFAULT 1,
17
+
created_by_user UUID NOT NULL REFERENCES users(id),
18
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
19
+
);
20
+
21
+
CREATE TABLE IF NOT EXISTS invite_code_uses (
22
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
23
+
code TEXT NOT NULL REFERENCES invite_codes(code),
24
+
used_by_user UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
25
+
used_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
26
+
UNIQUE(code, used_by_user)
27
+
);
28
+
29
+
-- OIII THIS TABLE CONTAINS PLAINTEXT PRIVATE KEYS, TODO: encrypt at rest!
30
+
CREATE TABLE IF NOT EXISTS user_keys (
31
+
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
32
+
-- Storing as raw bytes
33
+
-- secp256k1 is 32 bytes
34
+
key_bytes BYTEA NOT NULL,
35
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
36
+
);
37
+
38
+
CREATE TABLE IF NOT EXISTS repos (
39
+
user_id UUID PRIMARY KEY REFERENCES users(id) ON DELETE CASCADE,
40
+
repo_root_cid TEXT NOT NULL,
41
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
42
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
43
+
);
44
+
45
+
CREATE TABLE IF NOT EXISTS blocks (
46
+
cid BYTEA PRIMARY KEY,
47
+
data BYTEA NOT NULL,
48
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
49
+
);
50
+
51
+
-- A denormalized table to quickly query for records
52
+
-- TODO: Do I actually need this?
53
+
CREATE TABLE IF NOT EXISTS records (
54
+
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
55
+
repo_id UUID NOT NULL REFERENCES repos(user_id) ON DELETE CASCADE,
56
+
collection TEXT NOT NULL,
57
+
rkey TEXT NOT NULL,
58
+
record_cid TEXT NOT NULL,
59
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
60
+
UNIQUE(repo_id, collection, rkey)
61
+
);
62
+
63
+
CREATE TABLE IF NOT EXISTS blobs (
64
+
cid TEXT PRIMARY KEY,
65
+
mime_type TEXT NOT NULL,
66
+
size_bytes BIGINT NOT NULL,
67
+
created_by_user UUID NOT NULL REFERENCES users(id),
68
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
69
+
70
+
-- The key/path in the S3 bucket
71
+
storage_key TEXT NOT NULL
72
+
);
73
+
74
+
CREATE TABLE IF NOT EXISTS sessions (
75
+
access_jwt TEXT PRIMARY KEY,
76
+
refresh_jwt TEXT NOT NULL UNIQUE,
77
+
did TEXT NOT NULL REFERENCES users(did) ON DELETE CASCADE,
78
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
79
+
);
80
+
+219
src/api/repo.rs
+219
src/api/repo.rs
···
···
1
+
use axum::{
2
+
extract::State,
3
+
Json,
4
+
response::{IntoResponse, Response},
5
+
http::StatusCode,
6
+
};
7
+
use serde::{Deserialize, Serialize};
8
+
use serde_json::json;
9
+
use crate::state::AppState;
10
+
use chrono::Utc;
11
+
use sqlx::Row;
12
+
use cid::Cid;
13
+
use std::str::FromStr;
14
+
use jacquard_repo::{mst::Mst, commit::Commit, storage::BlockStore};
15
+
use jacquard::types::{string::{Nsid, Tid}, did::Did, integer::LimitedU32};
16
+
use tracing::error;
17
+
use std::sync::Arc;
18
+
19
+
#[derive(Deserialize)]
20
+
#[allow(dead_code)]
21
+
pub struct CreateRecordInput {
22
+
pub repo: String,
23
+
pub collection: String,
24
+
pub rkey: Option<String>,
25
+
pub validate: Option<bool>,
26
+
pub record: serde_json::Value,
27
+
#[serde(rename = "swapCommit")]
28
+
pub swap_commit: Option<String>,
29
+
}
30
+
31
+
#[derive(Serialize)]
32
+
#[serde(rename_all = "camelCase")]
33
+
pub struct CreateRecordOutput {
34
+
pub uri: String,
35
+
pub cid: String,
36
+
}
37
+
38
+
pub async fn create_record(
39
+
State(state): State<AppState>,
40
+
headers: axum::http::HeaderMap,
41
+
Json(input): Json<CreateRecordInput>,
42
+
) -> Response {
43
+
let auth_header = headers.get("Authorization");
44
+
if auth_header.is_none() {
45
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationRequired"}))).into_response();
46
+
}
47
+
let token = auth_header.unwrap().to_str().unwrap_or("").replace("Bearer ", "");
48
+
49
+
if let Err(_) = crate::auth::verify_token(&token) {
50
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed", "message": "Invalid token"}))).into_response();
51
+
}
52
+
53
+
let session = sqlx::query("SELECT did FROM sessions WHERE access_jwt = $1")
54
+
.bind(&token)
55
+
.fetch_optional(&state.db)
56
+
.await
57
+
.unwrap_or(None);
58
+
59
+
let did = match session {
60
+
Some(row) => row.get::<String, _>("did"),
61
+
None => return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed"}))).into_response(),
62
+
};
63
+
64
+
if input.repo != did {
65
+
return (StatusCode::FORBIDDEN, Json(json!({"error": "InvalidRepo", "message": "Repo does not match authenticated user"}))).into_response();
66
+
}
67
+
68
+
let user_query = sqlx::query("SELECT id FROM users WHERE did = $1")
69
+
.bind(&did)
70
+
.fetch_optional(&state.db)
71
+
.await;
72
+
73
+
let user_id: uuid::Uuid = match user_query {
74
+
Ok(Some(row)) => row.get("id"),
75
+
_ => return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError", "message": "User not found"}))).into_response(),
76
+
};
77
+
78
+
let repo_root_query = sqlx::query("SELECT repo_root_cid FROM repos WHERE user_id = $1")
79
+
.bind(user_id)
80
+
.fetch_optional(&state.db)
81
+
.await;
82
+
83
+
let current_root_cid = match repo_root_query {
84
+
Ok(Some(row)) => {
85
+
let cid_str: String = row.get("repo_root_cid");
86
+
Cid::from_str(&cid_str).ok()
87
+
},
88
+
_ => None,
89
+
};
90
+
91
+
if current_root_cid.is_none() {
92
+
error!("Repo root not found for user {}", did);
93
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError", "message": "Repo root not found"}))).into_response();
94
+
}
95
+
let current_root_cid = current_root_cid.unwrap();
96
+
97
+
let commit_bytes = match state.block_store.get(¤t_root_cid).await {
98
+
Ok(Some(b)) => b,
99
+
Ok(None) => {
100
+
error!("Commit block not found: {}", current_root_cid);
101
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
102
+
},
103
+
Err(e) => {
104
+
error!("Failed to load commit block: {:?}", e);
105
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
106
+
}
107
+
};
108
+
109
+
let commit = match Commit::from_cbor(&commit_bytes) {
110
+
Ok(c) => c,
111
+
Err(e) => {
112
+
error!("Failed to parse commit: {:?}", e);
113
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
114
+
}
115
+
};
116
+
117
+
let mst_root = commit.data;
118
+
let store = Arc::new(state.block_store.clone());
119
+
let mst = Mst::load(store.clone(), mst_root, None);
120
+
121
+
let collection_nsid = match input.collection.parse::<Nsid>() {
122
+
Ok(n) => n,
123
+
Err(_) => return (StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidCollection"}))).into_response(),
124
+
};
125
+
126
+
let rkey = input.rkey.unwrap_or_else(|| {
127
+
Utc::now().format("%Y%m%d%H%M%S%f").to_string()
128
+
});
129
+
130
+
let mut record_bytes = Vec::new();
131
+
if let Err(e) = serde_ipld_dagcbor::to_writer(&mut record_bytes, &input.record) {
132
+
error!("Error serializing record: {:?}", e);
133
+
return (StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidRecord", "message": "Failed to serialize record"}))).into_response();
134
+
}
135
+
136
+
let record_cid = match state.block_store.put(&record_bytes).await {
137
+
Ok(c) => c,
138
+
Err(e) => {
139
+
error!("Failed to save record block: {:?}", e);
140
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
141
+
}
142
+
};
143
+
144
+
let key = format!("{}/{}", collection_nsid, rkey);
145
+
if let Err(e) = mst.update(&key, record_cid).await {
146
+
error!("Failed to update MST: {:?}", e);
147
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
148
+
}
149
+
150
+
let new_mst_root = match mst.root().await {
151
+
Ok(c) => c,
152
+
Err(e) => {
153
+
error!("Failed to get new MST root: {:?}", e);
154
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
155
+
}
156
+
};
157
+
158
+
let did_obj = match Did::new(&did) {
159
+
Ok(d) => d,
160
+
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError", "message": "Invalid DID"}))).into_response(),
161
+
};
162
+
163
+
let rev = Tid::now(LimitedU32::MIN);
164
+
165
+
let new_commit = Commit::new_unsigned(
166
+
did_obj,
167
+
new_mst_root,
168
+
rev,
169
+
Some(current_root_cid)
170
+
);
171
+
172
+
let new_commit_bytes = match new_commit.to_cbor() {
173
+
Ok(b) => b,
174
+
Err(e) => {
175
+
error!("Failed to serialize new commit: {:?}", e);
176
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
177
+
}
178
+
};
179
+
180
+
let new_root_cid = match state.block_store.put(&new_commit_bytes).await {
181
+
Ok(c) => c,
182
+
Err(e) => {
183
+
error!("Failed to save new commit: {:?}", e);
184
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
185
+
}
186
+
};
187
+
188
+
let update_repo = sqlx::query("UPDATE repos SET repo_root_cid = $1 WHERE user_id = $2")
189
+
.bind(new_root_cid.to_string())
190
+
.bind(user_id)
191
+
.execute(&state.db)
192
+
.await;
193
+
194
+
if let Err(e) = update_repo {
195
+
error!("Failed to update repo root in DB: {:?}", e);
196
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
197
+
}
198
+
199
+
let record_insert = sqlx::query(
200
+
"INSERT INTO records (repo_id, collection, rkey, record_cid) VALUES ($1, $2, $3, $4)
201
+
ON CONFLICT (repo_id, collection, rkey) DO UPDATE SET record_cid = $4, created_at = NOW()"
202
+
)
203
+
.bind(user_id)
204
+
.bind(&input.collection)
205
+
.bind(&rkey)
206
+
.bind(record_cid.to_string())
207
+
.execute(&state.db)
208
+
.await;
209
+
210
+
if let Err(e) = record_insert {
211
+
error!("Error inserting record index: {:?}", e);
212
+
}
213
+
214
+
let output = CreateRecordOutput {
215
+
uri: format!("at://{}/{}/{}", input.repo, input.collection, rkey),
216
+
cid: record_cid.to_string(),
217
+
};
218
+
(StatusCode::OK, Json(output)).into_response()
219
+
}
+483
src/api/server.rs
+483
src/api/server.rs
···
···
1
+
use axum::{
2
+
extract::State,
3
+
Json,
4
+
response::{IntoResponse, Response},
5
+
http::StatusCode,
6
+
};
7
+
use serde::{Deserialize, Serialize};
8
+
use serde_json::json;
9
+
use crate::state::AppState;
10
+
use sqlx::Row;
11
+
use bcrypt::{hash, verify, DEFAULT_COST};
12
+
use tracing::{info, error, warn};
13
+
use jacquard_repo::{mst::Mst, commit::Commit, storage::BlockStore};
14
+
use jacquard::types::{string::Tid, did::Did, integer::LimitedU32};
15
+
use std::sync::Arc;
16
+
17
+
#[derive(Deserialize)]
18
+
pub struct CreateAccountInput {
19
+
pub handle: String,
20
+
pub email: String,
21
+
pub password: String,
22
+
#[serde(rename = "inviteCode")]
23
+
pub invite_code: Option<String>,
24
+
}
25
+
26
+
#[derive(Serialize)]
27
+
#[serde(rename_all = "camelCase")]
28
+
pub struct CreateAccountOutput {
29
+
pub access_jwt: String,
30
+
pub refresh_jwt: String,
31
+
pub handle: String,
32
+
pub did: String,
33
+
}
34
+
35
+
pub async fn create_account(
36
+
State(state): State<AppState>,
37
+
Json(input): Json<CreateAccountInput>,
38
+
) -> Response {
39
+
info!("create_account hit: {}", input.handle);
40
+
if input.handle.contains('!') || input.handle.contains('@') {
41
+
return (StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidHandle", "message": "Handle contains invalid characters"}))).into_response();
42
+
}
43
+
44
+
let mut tx = match state.db.begin().await {
45
+
Ok(tx) => tx,
46
+
Err(e) => {
47
+
error!("Error starting transaction: {:?}", e);
48
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
49
+
}
50
+
};
51
+
52
+
let exists_query = sqlx::query("SELECT 1 FROM users WHERE handle = $1")
53
+
.bind(&input.handle)
54
+
.fetch_optional(&mut *tx)
55
+
.await;
56
+
57
+
match exists_query {
58
+
Ok(Some(_)) => return (StatusCode::BAD_REQUEST, Json(json!({"error": "HandleTaken", "message": "Handle already taken"}))).into_response(),
59
+
Err(e) => {
60
+
error!("Error checking handle: {:?}", e);
61
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
62
+
}
63
+
Ok(None) => {}
64
+
}
65
+
66
+
if let Some(code) = &input.invite_code {
67
+
let invite_query = sqlx::query("SELECT available_uses FROM invite_codes WHERE code = $1 FOR UPDATE")
68
+
.bind(code)
69
+
.fetch_optional(&mut *tx)
70
+
.await;
71
+
72
+
match invite_query {
73
+
Ok(Some(row)) => {
74
+
let uses: i32 = row.get("available_uses");
75
+
if uses <= 0 {
76
+
return (StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidInviteCode", "message": "Invite code exhausted"}))).into_response();
77
+
}
78
+
79
+
let update_invite = sqlx::query("UPDATE invite_codes SET available_uses = available_uses - 1 WHERE code = $1")
80
+
.bind(code)
81
+
.execute(&mut *tx)
82
+
.await;
83
+
84
+
if let Err(e) = update_invite {
85
+
error!("Error updating invite code: {:?}", e);
86
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
87
+
}
88
+
},
89
+
Ok(None) => return (StatusCode::BAD_REQUEST, Json(json!({"error": "InvalidInviteCode", "message": "Invite code not found"}))).into_response(),
90
+
Err(e) => {
91
+
error!("Error checking invite code: {:?}", e);
92
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
93
+
}
94
+
}
95
+
}
96
+
97
+
let did = format!("did:plc:{}", uuid::Uuid::new_v4());
98
+
99
+
let password_hash = match hash(&input.password, DEFAULT_COST) {
100
+
Ok(h) => h,
101
+
Err(e) => {
102
+
error!("Error hashing password: {:?}", e);
103
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
104
+
}
105
+
};
106
+
107
+
let user_insert = sqlx::query("INSERT INTO users (handle, email, did, password_hash) VALUES ($1, $2, $3, $4) RETURNING id")
108
+
.bind(&input.handle)
109
+
.bind(&input.email)
110
+
.bind(&did)
111
+
.bind(&password_hash)
112
+
.fetch_one(&mut *tx)
113
+
.await;
114
+
115
+
let user_id: uuid::Uuid = match user_insert {
116
+
Ok(row) => row.get("id"),
117
+
Err(e) => {
118
+
error!("Error inserting user: {:?}", e);
119
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
120
+
}
121
+
};
122
+
123
+
let store = Arc::new(state.block_store.clone());
124
+
let mst = Mst::new(store.clone());
125
+
let mst_root = match mst.root().await {
126
+
Ok(c) => c,
127
+
Err(e) => {
128
+
error!("Error creating MST root: {:?}", e);
129
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
130
+
}
131
+
};
132
+
133
+
let did_obj = match Did::new(&did) {
134
+
Ok(d) => d,
135
+
Err(_) => return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError", "message": "Invalid DID"}))).into_response(),
136
+
};
137
+
138
+
let rev = Tid::now(LimitedU32::MIN);
139
+
140
+
let commit = Commit::new_unsigned(
141
+
did_obj,
142
+
mst_root,
143
+
rev,
144
+
None
145
+
);
146
+
147
+
let commit_bytes = match commit.to_cbor() {
148
+
Ok(b) => b,
149
+
Err(e) => {
150
+
error!("Error serializing genesis commit: {:?}", e);
151
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
152
+
}
153
+
};
154
+
155
+
let commit_cid = match state.block_store.put(&commit_bytes).await {
156
+
Ok(c) => c,
157
+
Err(e) => {
158
+
error!("Error saving genesis commit: {:?}", e);
159
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
160
+
}
161
+
};
162
+
163
+
let repo_insert = sqlx::query("INSERT INTO repos (user_id, repo_root_cid) VALUES ($1, $2)")
164
+
.bind(user_id)
165
+
.bind(commit_cid.to_string())
166
+
.execute(&mut *tx)
167
+
.await;
168
+
169
+
if let Err(e) = repo_insert {
170
+
error!("Error initializing repo: {:?}", e);
171
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
172
+
}
173
+
174
+
if let Some(code) = &input.invite_code {
175
+
let use_insert = sqlx::query("INSERT INTO invite_code_uses (code, used_by_user) VALUES ($1, $2)")
176
+
.bind(code)
177
+
.bind(user_id)
178
+
.execute(&mut *tx)
179
+
.await;
180
+
181
+
if let Err(e) = use_insert {
182
+
error!("Error recording invite usage: {:?}", e);
183
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
184
+
}
185
+
}
186
+
187
+
let access_jwt = crate::auth::create_access_token(&did).map_err(|e| {
188
+
error!("Error creating access token: {:?}", e);
189
+
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response()
190
+
});
191
+
let access_jwt = match access_jwt {
192
+
Ok(t) => t,
193
+
Err(r) => return r,
194
+
};
195
+
196
+
let refresh_jwt = crate::auth::create_refresh_token(&did).map_err(|e| {
197
+
error!("Error creating refresh token: {:?}", e);
198
+
(StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response()
199
+
});
200
+
let refresh_jwt = match refresh_jwt {
201
+
Ok(t) => t,
202
+
Err(r) => return r,
203
+
};
204
+
205
+
let session_insert = sqlx::query("INSERT INTO sessions (access_jwt, refresh_jwt, did) VALUES ($1, $2, $3)")
206
+
.bind(&access_jwt)
207
+
.bind(&refresh_jwt)
208
+
.bind(&did)
209
+
.execute(&mut *tx)
210
+
.await;
211
+
212
+
if let Err(e) = session_insert {
213
+
error!("Error inserting session: {:?}", e);
214
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
215
+
}
216
+
217
+
if let Err(e) = tx.commit().await {
218
+
error!("Error committing transaction: {:?}", e);
219
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
220
+
}
221
+
222
+
(StatusCode::OK, Json(CreateAccountOutput {
223
+
access_jwt,
224
+
refresh_jwt,
225
+
handle: input.handle,
226
+
did,
227
+
})).into_response()
228
+
}
229
+
230
+
#[derive(Deserialize)]
231
+
pub struct CreateSessionInput {
232
+
pub identifier: String,
233
+
pub password: String,
234
+
}
235
+
236
+
#[derive(Serialize)]
237
+
#[serde(rename_all = "camelCase")]
238
+
pub struct CreateSessionOutput {
239
+
pub access_jwt: String,
240
+
pub refresh_jwt: String,
241
+
pub handle: String,
242
+
pub did: String,
243
+
}
244
+
245
+
pub async fn create_session(
246
+
State(state): State<AppState>,
247
+
Json(input): Json<CreateSessionInput>,
248
+
) -> Response {
249
+
info!("create_session: identifier='{}'", input.identifier);
250
+
251
+
let user_row = sqlx::query("SELECT did, handle, password_hash FROM users WHERE handle = $1 OR email = $1")
252
+
.bind(&input.identifier)
253
+
.fetch_optional(&state.db)
254
+
.await;
255
+
256
+
match user_row {
257
+
Ok(Some(row)) => {
258
+
let stored_hash: String = row.get("password_hash");
259
+
260
+
if verify(&input.password, &stored_hash).unwrap_or(false) {
261
+
let did: String = row.get("did");
262
+
let handle: String = row.get("handle");
263
+
264
+
let access_jwt = match crate::auth::create_access_token(&did) {
265
+
Ok(t) => t,
266
+
Err(e) => {
267
+
error!("Failed to create access token: {:?}", e);
268
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
269
+
}
270
+
};
271
+
272
+
let refresh_jwt = match crate::auth::create_refresh_token(&did) {
273
+
Ok(t) => t,
274
+
Err(e) => {
275
+
error!("Failed to create refresh token: {:?}", e);
276
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
277
+
}
278
+
};
279
+
280
+
let session_insert = sqlx::query("INSERT INTO sessions (access_jwt, refresh_jwt, did) VALUES ($1, $2, $3)")
281
+
.bind(&access_jwt)
282
+
.bind(&refresh_jwt)
283
+
.bind(&did)
284
+
.execute(&state.db)
285
+
.await;
286
+
287
+
match session_insert {
288
+
Ok(_) => {
289
+
return (StatusCode::OK, Json(CreateSessionOutput {
290
+
access_jwt,
291
+
refresh_jwt,
292
+
handle,
293
+
did,
294
+
})).into_response();
295
+
},
296
+
Err(e) => {
297
+
error!("Failed to insert session: {:?}", e);
298
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
299
+
}
300
+
}
301
+
} else {
302
+
warn!("Password verification failed for identifier: {}", input.identifier);
303
+
}
304
+
},
305
+
Ok(None) => {
306
+
warn!("User not found for identifier: {}", input.identifier);
307
+
},
308
+
Err(e) => {
309
+
error!("Database error fetching user: {:?}", e);
310
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
311
+
}
312
+
}
313
+
314
+
(StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed", "message": "Invalid identifier or password"}))).into_response()
315
+
}
316
+
317
+
pub async fn get_session(
318
+
State(state): State<AppState>,
319
+
headers: axum::http::HeaderMap,
320
+
) -> Response {
321
+
let auth_header = headers.get("Authorization");
322
+
if auth_header.is_none() {
323
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationRequired"}))).into_response();
324
+
}
325
+
326
+
let token = auth_header.unwrap().to_str().unwrap_or("").replace("Bearer ", "");
327
+
328
+
if let Err(_) = crate::auth::verify_token(&token) {
329
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed", "message": "Invalid token"}))).into_response();
330
+
}
331
+
332
+
let result = sqlx::query(
333
+
r#"
334
+
SELECT u.handle, u.did, u.email
335
+
FROM sessions s
336
+
JOIN users u ON s.did = u.did
337
+
WHERE s.access_jwt = $1
338
+
"#
339
+
)
340
+
.bind(token)
341
+
.fetch_optional(&state.db)
342
+
.await;
343
+
344
+
match result {
345
+
Ok(Some(row)) => {
346
+
let handle: String = row.get("handle");
347
+
let did: String = row.get("did");
348
+
let email: String = row.get("email");
349
+
350
+
return (StatusCode::OK, Json(json!({
351
+
"handle": handle,
352
+
"did": did,
353
+
"email": email,
354
+
"didDoc": {}
355
+
}))).into_response();
356
+
},
357
+
Ok(None) => {
358
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed"}))).into_response();
359
+
},
360
+
Err(e) => {
361
+
error!("Database error in get_session: {:?}", e);
362
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
363
+
}
364
+
}
365
+
}
366
+
367
+
pub async fn delete_session(
368
+
State(state): State<AppState>,
369
+
headers: axum::http::HeaderMap,
370
+
) -> Response {
371
+
let auth_header = headers.get("Authorization");
372
+
if auth_header.is_none() {
373
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationRequired"}))).into_response();
374
+
}
375
+
376
+
let token = auth_header.unwrap().to_str().unwrap_or("").replace("Bearer ", "");
377
+
378
+
let result = sqlx::query("DELETE FROM sessions WHERE access_jwt = $1")
379
+
.bind(token)
380
+
.execute(&state.db)
381
+
.await;
382
+
383
+
match result {
384
+
Ok(res) => {
385
+
if res.rows_affected() > 0 {
386
+
return (StatusCode::OK, Json(json!({}))).into_response();
387
+
}
388
+
},
389
+
Err(e) => {
390
+
error!("Database error in delete_session: {:?}", e);
391
+
}
392
+
}
393
+
394
+
(StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed"}))).into_response()
395
+
}
396
+
397
+
pub async fn refresh_session(
398
+
State(state): State<AppState>,
399
+
headers: axum::http::HeaderMap,
400
+
) -> Response {
401
+
let auth_header = headers.get("Authorization");
402
+
if auth_header.is_none() {
403
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationRequired"}))).into_response();
404
+
}
405
+
406
+
let refresh_token = auth_header.unwrap().to_str().unwrap_or("").replace("Bearer ", "");
407
+
408
+
if let Err(_) = crate::auth::verify_token(&refresh_token) {
409
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed", "message": "Invalid refresh token"}))).into_response();
410
+
}
411
+
412
+
let session = sqlx::query("SELECT did FROM sessions WHERE refresh_jwt = $1")
413
+
.bind(&refresh_token)
414
+
.fetch_optional(&state.db)
415
+
.await;
416
+
417
+
match session {
418
+
Ok(Some(session_row)) => {
419
+
let did: String = session_row.get("did");
420
+
let new_access_jwt = match crate::auth::create_access_token(&did) {
421
+
Ok(t) => t,
422
+
Err(e) => {
423
+
error!("Failed to create access token: {:?}", e);
424
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
425
+
}
426
+
};
427
+
let new_refresh_jwt = match crate::auth::create_refresh_token(&did) {
428
+
Ok(t) => t,
429
+
Err(e) => {
430
+
error!("Failed to create refresh token: {:?}", e);
431
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
432
+
}
433
+
};
434
+
435
+
let update = sqlx::query("UPDATE sessions SET access_jwt = $1, refresh_jwt = $2 WHERE refresh_jwt = $3")
436
+
.bind(&new_access_jwt)
437
+
.bind(&new_refresh_jwt)
438
+
.bind(&refresh_token)
439
+
.execute(&state.db)
440
+
.await;
441
+
442
+
match update {
443
+
Ok(_) => {
444
+
let user = sqlx::query("SELECT handle FROM users WHERE did = $1")
445
+
.bind(&did)
446
+
.fetch_optional(&state.db)
447
+
.await;
448
+
449
+
match user {
450
+
Ok(Some(u)) => {
451
+
let handle: String = u.get("handle");
452
+
return (StatusCode::OK, Json(json!({
453
+
"accessJwt": new_access_jwt,
454
+
"refreshJwt": new_refresh_jwt,
455
+
"handle": handle,
456
+
"did": did
457
+
}))).into_response();
458
+
},
459
+
Ok(None) => {
460
+
error!("User not found for existing session: {}", did);
461
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
462
+
},
463
+
Err(e) => {
464
+
error!("Database error fetching user: {:?}", e);
465
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
466
+
}
467
+
}
468
+
},
469
+
Err(e) => {
470
+
error!("Database error updating session: {:?}", e);
471
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
472
+
}
473
+
}
474
+
},
475
+
Ok(None) => {
476
+
return (StatusCode::UNAUTHORIZED, Json(json!({"error": "AuthenticationFailed", "message": "Invalid refresh token"}))).into_response();
477
+
},
478
+
Err(e) => {
479
+
error!("Database error fetching session: {:?}", e);
480
+
return (StatusCode::INTERNAL_SERVER_ERROR, Json(json!({"error": "InternalError"}))).into_response();
481
+
}
482
+
}
483
+
}
+59
src/auth.rs
+59
src/auth.rs
···
···
1
+
use jsonwebtoken::{encode, decode, Header, Validation, EncodingKey, DecodingKey, TokenData};
2
+
use serde::{Deserialize, Serialize};
3
+
use chrono::{Utc, Duration};
4
+
use std::env;
5
+
6
+
#[derive(Debug, Serialize, Deserialize)]
7
+
pub struct Claims {
8
+
// DID type shit
9
+
pub sub: String,
10
+
pub exp: usize,
11
+
pub iat: usize,
12
+
pub scope: String,
13
+
pub jti: String,
14
+
}
15
+
16
+
pub fn create_access_token(did: &str) -> Result<String, jsonwebtoken::errors::Error> {
17
+
let secret = env::var("JWT_SECRET").unwrap_or_else(|_| "secret".to_string());
18
+
let expiration = Utc::now()
19
+
.checked_add_signed(Duration::minutes(15))
20
+
.expect("valid timestamp")
21
+
.timestamp();
22
+
23
+
let claims = Claims {
24
+
sub: did.to_owned(),
25
+
exp: expiration as usize,
26
+
iat: Utc::now().timestamp() as usize,
27
+
scope: "access".to_string(),
28
+
jti: uuid::Uuid::new_v4().to_string(),
29
+
};
30
+
31
+
encode(&Header::default(), &claims, &EncodingKey::from_secret(secret.as_ref()))
32
+
}
33
+
34
+
pub fn create_refresh_token(did: &str) -> Result<String, jsonwebtoken::errors::Error> {
35
+
let secret = env::var("JWT_SECRET").unwrap_or_else(|_| "secret".to_string());
36
+
let expiration = Utc::now()
37
+
.checked_add_signed(Duration::days(7))
38
+
.expect("valid timestamp")
39
+
.timestamp();
40
+
41
+
let claims = Claims {
42
+
sub: did.to_owned(),
43
+
exp: expiration as usize,
44
+
iat: Utc::now().timestamp() as usize,
45
+
scope: "refresh".to_string(),
46
+
jti: uuid::Uuid::new_v4().to_string(),
47
+
};
48
+
49
+
encode(&Header::default(), &claims, &EncodingKey::from_secret(secret.as_ref()))
50
+
}
51
+
52
+
pub fn verify_token(token: &str) -> Result<TokenData<Claims>, jsonwebtoken::errors::Error> {
53
+
let secret = env::var("JWT_SECRET").unwrap_or_else(|_| "secret".to_string());
54
+
decode::<Claims>(
55
+
token,
56
+
&DecodingKey::from_secret(secret.as_ref()),
57
+
&Validation::default(),
58
+
)
59
+
}
+73
src/main.rs
+73
src/main.rs
···
···
1
+
mod api;
2
+
mod state;
3
+
mod auth;
4
+
mod repo;
5
+
6
+
use axum::{
7
+
extract::State,
8
+
routing::{get, post},
9
+
Router,
10
+
Json,
11
+
response::IntoResponse,
12
+
http::StatusCode,
13
+
};
14
+
use serde_json::json;
15
+
use std::net::SocketAddr;
16
+
use state::AppState;
17
+
use tracing::{info, error};
18
+
19
+
#[tokio::main]
20
+
async fn main() {
21
+
dotenvy::dotenv().ok();
22
+
tracing_subscriber::fmt::init();
23
+
24
+
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
25
+
26
+
let pool = sqlx::postgres::PgPoolOptions::new()
27
+
.max_connections(5)
28
+
.connect(&database_url)
29
+
.await
30
+
.expect("Failed to connect to Postgres");
31
+
32
+
sqlx::migrate!("./migrations")
33
+
.run(&pool)
34
+
.await
35
+
.expect("Failed to run migrations");
36
+
37
+
let state = AppState::new(pool);
38
+
39
+
let app = Router::new()
40
+
.route("/health", get(health))
41
+
.route("/xrpc/com.atproto.server.describeServer", get(describe_server))
42
+
.route("/xrpc/com.atproto.server.createAccount", post(api::server::create_account))
43
+
.route("/xrpc/com.atproto.server.createSession", post(api::server::create_session))
44
+
.route("/xrpc/com.atproto.server.getSession", get(api::server::get_session))
45
+
.route("/xrpc/com.atproto.server.deleteSession", post(api::server::delete_session))
46
+
.route("/xrpc/com.atproto.server.refreshSession", post(api::server::refresh_session))
47
+
.route("/xrpc/com.atproto.repo.createRecord", post(api::repo::create_record))
48
+
.with_state(state);
49
+
50
+
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
51
+
info!("listening on {}", addr);
52
+
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
53
+
axum::serve(listener, app).await.unwrap();
54
+
}
55
+
56
+
async fn health(State(state): State<AppState>) -> impl IntoResponse {
57
+
match sqlx::query("SELECT 1").execute(&state.db).await {
58
+
Ok(_) => (StatusCode::OK, "OK"),
59
+
Err(e) => {
60
+
error!("Health check failed: {:?}", e);
61
+
(StatusCode::SERVICE_UNAVAILABLE, "Service Unavailable")
62
+
}
63
+
}
64
+
}
65
+
66
+
async fn describe_server() -> impl IntoResponse {
67
+
let domains_str = std::env::var("AVAILABLE_USER_DOMAINS").unwrap_or_else(|_| "example.com".to_string());
68
+
let domains: Vec<&str> = domains_str.split(',').map(|s| s.trim()).collect();
69
+
70
+
Json(json!({
71
+
"availableUserDomains": domains
72
+
}))
73
+
}
+94
src/repo/mod.rs
+94
src/repo/mod.rs
···
···
1
+
use jacquard_repo::storage::BlockStore;
2
+
use jacquard_repo::error::RepoError;
3
+
use jacquard_repo::repo::CommitData;
4
+
use cid::Cid;
5
+
use sqlx::{PgPool, Row};
6
+
use bytes::Bytes;
7
+
use sha2::{Sha256, Digest};
8
+
use multihash::Multihash;
9
+
10
+
#[derive(Clone)]
11
+
pub struct PostgresBlockStore {
12
+
pool: PgPool,
13
+
}
14
+
15
+
impl PostgresBlockStore {
16
+
pub fn new(pool: PgPool) -> Self {
17
+
Self { pool }
18
+
}
19
+
}
20
+
21
+
impl BlockStore for PostgresBlockStore {
22
+
async fn get(&self, cid: &Cid) -> Result<Option<Bytes>, RepoError> {
23
+
let cid_bytes = cid.to_bytes();
24
+
let row = sqlx::query("SELECT data FROM blocks WHERE cid = $1")
25
+
.bind(cid_bytes)
26
+
.fetch_optional(&self.pool)
27
+
.await
28
+
.map_err(|e| RepoError::storage(e))?;
29
+
30
+
match row {
31
+
Some(row) => {
32
+
let data: Vec<u8> = row.get("data");
33
+
Ok(Some(Bytes::from(data)))
34
+
},
35
+
None => Ok(None),
36
+
}
37
+
}
38
+
39
+
async fn put(&self, data: &[u8]) -> Result<Cid, RepoError> {
40
+
let mut hasher = Sha256::new();
41
+
hasher.update(data);
42
+
let hash = hasher.finalize();
43
+
let multihash = Multihash::wrap(0x12, &hash).unwrap();
44
+
let cid = Cid::new_v1(0x71, multihash);
45
+
let cid_bytes = cid.to_bytes();
46
+
47
+
sqlx::query("INSERT INTO blocks (cid, data) VALUES ($1, $2) ON CONFLICT (cid) DO NOTHING")
48
+
.bind(cid_bytes)
49
+
.bind(data)
50
+
.execute(&self.pool)
51
+
.await
52
+
.map_err(|e| RepoError::storage(e))?;
53
+
54
+
Ok(cid)
55
+
}
56
+
57
+
async fn has(&self, cid: &Cid) -> Result<bool, RepoError> {
58
+
let cid_bytes = cid.to_bytes();
59
+
let row = sqlx::query("SELECT 1 FROM blocks WHERE cid = $1")
60
+
.bind(cid_bytes)
61
+
.fetch_optional(&self.pool)
62
+
.await
63
+
.map_err(|e| RepoError::storage(e))?;
64
+
65
+
Ok(row.is_some())
66
+
}
67
+
68
+
async fn put_many(&self, blocks: impl IntoIterator<Item = (Cid, Bytes)> + Send) -> Result<(), RepoError> {
69
+
let blocks: Vec<_> = blocks.into_iter().collect();
70
+
for (cid, data) in blocks {
71
+
let cid_bytes = cid.to_bytes();
72
+
sqlx::query("INSERT INTO blocks (cid, data) VALUES ($1, $2) ON CONFLICT (cid) DO NOTHING")
73
+
.bind(cid_bytes)
74
+
.bind(data.as_ref())
75
+
.execute(&self.pool)
76
+
.await
77
+
.map_err(|e| RepoError::storage(e))?;
78
+
}
79
+
Ok(())
80
+
}
81
+
82
+
async fn get_many(&self, cids: &[Cid]) -> Result<Vec<Option<Bytes>>, RepoError> {
83
+
let mut results = Vec::new();
84
+
for cid in cids {
85
+
results.push(self.get(cid).await?);
86
+
}
87
+
Ok(results)
88
+
}
89
+
90
+
async fn apply_commit(&self, commit: CommitData) -> Result<(), RepoError> {
91
+
self.put_many(commit.blocks).await?;
92
+
Ok(())
93
+
}
94
+
}
+15
src/state.rs
+15
src/state.rs
···
···
1
+
use sqlx::PgPool;
2
+
use crate::repo::PostgresBlockStore;
3
+
4
+
#[derive(Clone)]
5
+
pub struct AppState {
6
+
pub db: PgPool,
7
+
pub block_store: PostgresBlockStore,
8
+
}
9
+
10
+
impl AppState {
11
+
pub fn new(db: PgPool) -> Self {
12
+
let block_store = PostgresBlockStore::new(db.clone());
13
+
Self { db, block_store }
14
+
}
15
+
}
+36
tests/actor.rs
+36
tests/actor.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
use reqwest::StatusCode;
4
+
5
+
#[tokio::test]
6
+
async fn test_get_profile() {
7
+
let client = client();
8
+
let params = [
9
+
("actor", AUTH_DID),
10
+
];
11
+
let res = client.get(format!("{}/xrpc/app.bsky.actor.getProfile", BASE_URL))
12
+
.query(¶ms)
13
+
.bearer_auth(AUTH_TOKEN)
14
+
.send()
15
+
.await
16
+
.expect("Failed to send request");
17
+
18
+
assert_eq!(res.status(), StatusCode::OK);
19
+
}
20
+
21
+
#[tokio::test]
22
+
async fn test_search_actors() {
23
+
let client = client();
24
+
let params = [
25
+
("q", "test"),
26
+
("limit", "10"),
27
+
];
28
+
let res = client.get(format!("{}/xrpc/app.bsky.actor.searchActors", BASE_URL))
29
+
.query(¶ms)
30
+
.bearer_auth(AUTH_TOKEN)
31
+
.send()
32
+
.await
33
+
.expect("Failed to send request");
34
+
35
+
assert_eq!(res.status(), StatusCode::OK);
36
+
}
+101
tests/common/mod.rs
+101
tests/common/mod.rs
···
···
1
+
use reqwest::{header, Client, StatusCode};
2
+
use serde_json::{json, Value};
3
+
use chrono::Utc;
4
+
#[allow(unused_imports)]
5
+
use std::collections::HashMap;
6
+
#[allow(unused_imports)]
7
+
use std::time::Duration;
8
+
9
+
pub const BASE_URL: &str = "http://127.0.0.1:3000";
10
+
#[allow(dead_code)]
11
+
pub const AUTH_TOKEN: &str = "test-token";
12
+
#[allow(dead_code)]
13
+
pub const BAD_AUTH_TOKEN: &str = "bad-token";
14
+
#[allow(dead_code)]
15
+
pub const AUTH_DID: &str = "did:plc:fake";
16
+
#[allow(dead_code)]
17
+
pub const TARGET_DID: &str = "did:plc:target";
18
+
19
+
pub fn client() -> Client {
20
+
Client::new()
21
+
}
22
+
23
+
#[allow(dead_code)]
24
+
pub async fn upload_test_blob(client: &Client, data: &'static str, mime: &'static str) -> Value {
25
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.uploadBlob", BASE_URL))
26
+
.header(header::CONTENT_TYPE, mime)
27
+
.bearer_auth(AUTH_TOKEN)
28
+
.body(data)
29
+
.send()
30
+
.await
31
+
.expect("Failed to send uploadBlob request");
32
+
33
+
assert_eq!(res.status(), StatusCode::OK, "Failed to upload blob");
34
+
let body: Value = res.json().await.expect("Blob upload response was not JSON");
35
+
body["blob"].clone()
36
+
}
37
+
38
+
39
+
#[allow(dead_code)]
40
+
pub async fn create_test_post(
41
+
client: &Client,
42
+
text: &str,
43
+
reply_to: Option<Value>
44
+
) -> (String, String, String) {
45
+
let collection = "app.bsky.feed.post";
46
+
let mut record = json!({
47
+
"$type": collection,
48
+
"text": text,
49
+
"createdAt": Utc::now().to_rfc3339()
50
+
});
51
+
52
+
if let Some(reply_obj) = reply_to {
53
+
record["reply"] = reply_obj;
54
+
}
55
+
56
+
let payload = json!({
57
+
"repo": AUTH_DID,
58
+
"collection": collection,
59
+
"record": record
60
+
});
61
+
62
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.createRecord", BASE_URL))
63
+
.bearer_auth(AUTH_TOKEN)
64
+
.json(&payload)
65
+
.send()
66
+
.await
67
+
.expect("Failed to send createRecord");
68
+
69
+
assert_eq!(res.status(), StatusCode::OK, "Failed to create post record");
70
+
let body: Value = res.json().await.expect("createRecord response was not JSON");
71
+
72
+
let uri = body["uri"].as_str().expect("Response had no URI").to_string();
73
+
let cid = body["cid"].as_str().expect("Response had no CID").to_string();
74
+
let rkey = uri.split('/').last().expect("URI was malformed").to_string();
75
+
76
+
(uri, cid, rkey)
77
+
}
78
+
79
+
pub async fn create_account_and_login(client: &Client) -> (String, String) {
80
+
let handle = format!("user_{}", uuid::Uuid::new_v4());
81
+
let payload = json!({
82
+
"handle": handle,
83
+
"email": format!("{}@example.com", handle),
84
+
"password": "password"
85
+
});
86
+
87
+
let res = client.post(format!("{}/xrpc/com.atproto.server.createAccount", BASE_URL))
88
+
.json(&payload)
89
+
.send()
90
+
.await
91
+
.expect("Failed to create account");
92
+
93
+
if res.status() != StatusCode::OK {
94
+
panic!("Failed to create account: {:?}", res.text().await);
95
+
}
96
+
97
+
let body: Value = res.json().await.expect("Invalid JSON");
98
+
let access_jwt = body["accessJwt"].as_str().expect("No accessJwt").to_string();
99
+
let did = body["did"].as_str().expect("No did").to_string();
100
+
(access_jwt, did)
101
+
}
+53
tests/feed.rs
+53
tests/feed.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
use reqwest::StatusCode;
4
+
5
+
use std::collections::HashMap;
6
+
7
+
#[tokio::test]
8
+
async fn test_get_timeline() {
9
+
let client = client();
10
+
let params = [("limit", "30")];
11
+
let res = client.get(format!("{}/xrpc/app.bsky.feed.getTimeline", BASE_URL))
12
+
.query(¶ms)
13
+
.bearer_auth(AUTH_TOKEN)
14
+
.send()
15
+
.await
16
+
.expect("Failed to send request");
17
+
18
+
assert_eq!(res.status(), StatusCode::OK);
19
+
}
20
+
21
+
#[tokio::test]
22
+
async fn test_get_author_feed() {
23
+
let client = client();
24
+
let params = [
25
+
("actor", AUTH_DID),
26
+
("limit", "30")
27
+
];
28
+
let res = client.get(format!("{}/xrpc/app.bsky.feed.getAuthorFeed", BASE_URL))
29
+
.query(¶ms)
30
+
.bearer_auth(AUTH_TOKEN)
31
+
.send()
32
+
.await
33
+
.expect("Failed to send request");
34
+
35
+
assert_eq!(res.status(), StatusCode::OK);
36
+
}
37
+
38
+
#[tokio::test]
39
+
async fn test_get_post_thread() {
40
+
let client = client();
41
+
let mut params = HashMap::new();
42
+
params.insert("uri", "at://did:plc:other/app.bsky.feed.post/3k12345");
43
+
params.insert("depth", "5");
44
+
45
+
let res = client.get(format!("{}/xrpc/app.bsky.feed.getPostThread", BASE_URL))
46
+
.query(¶ms)
47
+
.bearer_auth(AUTH_TOKEN)
48
+
.send()
49
+
.await
50
+
.expect("Failed to send request");
51
+
52
+
assert_eq!(res.status(), StatusCode::OK);
53
+
}
+68
tests/graph.rs
+68
tests/graph.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
use reqwest::StatusCode;
4
+
5
+
#[tokio::test]
6
+
async fn test_get_follows() {
7
+
let client = client();
8
+
let params = [
9
+
("actor", AUTH_DID),
10
+
];
11
+
let res = client.get(format!("{}/xrpc/app.bsky.graph.getFollows", BASE_URL))
12
+
.query(¶ms)
13
+
.bearer_auth(AUTH_TOKEN)
14
+
.send()
15
+
.await
16
+
.expect("Failed to send request");
17
+
18
+
assert_eq!(res.status(), StatusCode::OK);
19
+
}
20
+
21
+
#[tokio::test]
22
+
async fn test_get_followers() {
23
+
let client = client();
24
+
let params = [
25
+
("actor", AUTH_DID),
26
+
];
27
+
let res = client.get(format!("{}/xrpc/app.bsky.graph.getFollowers", BASE_URL))
28
+
.query(¶ms)
29
+
.bearer_auth(AUTH_TOKEN)
30
+
.send()
31
+
.await
32
+
.expect("Failed to send request");
33
+
34
+
assert_eq!(res.status(), StatusCode::OK);
35
+
}
36
+
37
+
#[tokio::test]
38
+
async fn test_get_mutes() {
39
+
let client = client();
40
+
let params = [
41
+
("limit", "25"),
42
+
];
43
+
let res = client.get(format!("{}/xrpc/app.bsky.graph.getMutes", BASE_URL))
44
+
.query(¶ms)
45
+
.bearer_auth(AUTH_TOKEN)
46
+
.send()
47
+
.await
48
+
.expect("Failed to send request");
49
+
50
+
assert_eq!(res.status(), StatusCode::OK);
51
+
}
52
+
53
+
#[tokio::test]
54
+
// User blocks, ie. not repo blocks ya know
55
+
async fn test_get_user_blocks() {
56
+
let client = client();
57
+
let params = [
58
+
("limit", "25"),
59
+
];
60
+
let res = client.get(format!("{}/xrpc/app.bsky.graph.getBlocks", BASE_URL))
61
+
.query(¶ms)
62
+
.bearer_auth(AUTH_TOKEN)
63
+
.send()
64
+
.await
65
+
.expect("Failed to send request");
66
+
67
+
assert_eq!(res.status(), StatusCode::OK);
68
+
}
+18
tests/identity.rs
+18
tests/identity.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
use reqwest::StatusCode;
4
+
5
+
#[tokio::test]
6
+
async fn test_resolve_handle() {
7
+
let client = client();
8
+
let params = [
9
+
("handle", "bsky.app"),
10
+
];
11
+
let res = client.get(format!("{}/xrpc/com.atproto.identity.resolveHandle", BASE_URL))
12
+
.query(¶ms)
13
+
.send()
14
+
.await
15
+
.expect("Failed to send request");
16
+
17
+
assert_eq!(res.status(), StatusCode::OK);
18
+
}
+936
tests/lifecycle.rs
+936
tests/lifecycle.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
4
+
use reqwest::StatusCode;
5
+
use serde_json::{json, Value};
6
+
use chrono::Utc;
7
+
use std::time::Duration;
8
+
9
+
use reqwest::Client;
10
+
#[allow(unused_imports)]
11
+
use std::collections::HashMap;
12
+
13
+
#[tokio::test]
14
+
async fn test_post_crud_lifecycle() {
15
+
let client = client();
16
+
let collection = "app.bsky.feed.post";
17
+
18
+
let rkey = format!("e2e_lifecycle_{}", Utc::now().timestamp_millis());
19
+
let now = Utc::now().to_rfc3339();
20
+
21
+
let original_text = "Hello from the lifecycle test!";
22
+
let create_payload = json!({
23
+
"repo": AUTH_DID,
24
+
"collection": collection,
25
+
"rkey": rkey,
26
+
"record": {
27
+
"$type": collection,
28
+
"text": original_text,
29
+
"createdAt": now
30
+
}
31
+
});
32
+
33
+
let create_res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
34
+
.bearer_auth(AUTH_TOKEN)
35
+
.json(&create_payload)
36
+
.send()
37
+
.await
38
+
.expect("Failed to send create request");
39
+
40
+
assert_eq!(create_res.status(), StatusCode::OK, "Failed to create record");
41
+
let create_body: Value = create_res.json().await.expect("create response was not JSON");
42
+
let uri = create_body["uri"].as_str().unwrap();
43
+
44
+
45
+
let params = [
46
+
("repo", AUTH_DID),
47
+
("collection", collection),
48
+
("rkey", &rkey),
49
+
];
50
+
let get_res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
51
+
.query(¶ms)
52
+
.send()
53
+
.await
54
+
.expect("Failed to send get request");
55
+
56
+
assert_eq!(get_res.status(), StatusCode::OK, "Failed to get record after create");
57
+
let get_body: Value = get_res.json().await.expect("get response was not JSON");
58
+
assert_eq!(get_body["uri"], uri);
59
+
assert_eq!(get_body["value"]["text"], original_text);
60
+
61
+
62
+
let updated_text = "This post has been updated.";
63
+
let update_payload = json!({
64
+
"repo": AUTH_DID,
65
+
"collection": collection,
66
+
"rkey": rkey,
67
+
"record": {
68
+
"$type": collection,
69
+
"text": updated_text,
70
+
"createdAt": now
71
+
}
72
+
});
73
+
74
+
let update_res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
75
+
.bearer_auth(AUTH_TOKEN)
76
+
.json(&update_payload)
77
+
.send()
78
+
.await
79
+
.expect("Failed to send update request");
80
+
81
+
assert_eq!(update_res.status(), StatusCode::OK, "Failed to update record");
82
+
83
+
84
+
let get_updated_res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
85
+
.query(¶ms)
86
+
.send()
87
+
.await
88
+
.expect("Failed to send get-after-update request");
89
+
90
+
assert_eq!(get_updated_res.status(), StatusCode::OK, "Failed to get record after update");
91
+
let get_updated_body: Value = get_updated_res.json().await.expect("get-updated response was not JSON");
92
+
assert_eq!(get_updated_body["value"]["text"], updated_text, "Text was not updated");
93
+
94
+
95
+
let delete_payload = json!({
96
+
"repo": AUTH_DID,
97
+
"collection": collection,
98
+
"rkey": rkey
99
+
});
100
+
101
+
let delete_res = client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
102
+
.bearer_auth(AUTH_TOKEN)
103
+
.json(&delete_payload)
104
+
.send()
105
+
.await
106
+
.expect("Failed to send delete request");
107
+
108
+
assert_eq!(delete_res.status(), StatusCode::OK, "Failed to delete record");
109
+
110
+
111
+
let get_deleted_res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
112
+
.query(¶ms)
113
+
.send()
114
+
.await
115
+
.expect("Failed to send get-after-delete request");
116
+
117
+
assert_eq!(get_deleted_res.status(), StatusCode::NOT_FOUND, "Record was found, but it should be deleted");
118
+
}
119
+
120
+
#[tokio::test]
121
+
async fn test_post_with_image_lifecycle() {
122
+
let client = client();
123
+
124
+
let now_str = Utc::now().to_rfc3339();
125
+
let fake_image_data = format!("This is a fake PNG for test at {}", now_str);
126
+
127
+
let image_blob = upload_test_blob(
128
+
&client,
129
+
Box::leak(fake_image_data.into_boxed_str()),
130
+
"image/png"
131
+
).await;
132
+
133
+
let blob_ref = image_blob["ref"].clone();
134
+
assert!(blob_ref.is_object(), "Blob ref is not an object");
135
+
136
+
137
+
let collection = "app.bsky.feed.post";
138
+
let rkey = format!("e2e_image_post_{}", Utc::now().timestamp_millis());
139
+
140
+
let create_payload = json!({
141
+
"repo": AUTH_DID,
142
+
"collection": collection,
143
+
"rkey": rkey,
144
+
"record": {
145
+
"$type": collection,
146
+
"text": "Check out this image!",
147
+
"createdAt": Utc::now().to_rfc3339(),
148
+
"embed": {
149
+
"$type": "app.bsky.embed.images",
150
+
"images": [
151
+
{
152
+
"image": image_blob,
153
+
"alt": "A test image"
154
+
}
155
+
]
156
+
}
157
+
}
158
+
});
159
+
160
+
let create_res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
161
+
.bearer_auth(AUTH_TOKEN)
162
+
.json(&create_payload)
163
+
.send()
164
+
.await
165
+
.expect("Failed to create image post");
166
+
167
+
assert_eq!(create_res.status(), StatusCode::OK, "Failed to create post with image");
168
+
169
+
170
+
let params = [
171
+
("repo", AUTH_DID),
172
+
("collection", collection),
173
+
("rkey", &rkey),
174
+
];
175
+
let get_res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
176
+
.query(¶ms)
177
+
.send()
178
+
.await
179
+
.expect("Failed to get image post");
180
+
181
+
assert_eq!(get_res.status(), StatusCode::OK, "Failed to get image post");
182
+
let get_body: Value = get_res.json().await.expect("get image post was not JSON");
183
+
184
+
let embed_image = &get_body["value"]["embed"]["images"][0]["image"];
185
+
assert!(embed_image.is_object(), "Embedded image is missing");
186
+
assert_eq!(embed_image["ref"], blob_ref, "Embedded blob ref does not match uploaded ref");
187
+
}
188
+
189
+
#[tokio::test]
190
+
async fn test_graph_lifecycle_follow_unfollow() {
191
+
let client = client();
192
+
let collection = "app.bsky.graph.follow";
193
+
194
+
let create_payload = json!({
195
+
"repo": AUTH_DID,
196
+
"collection": collection,
197
+
// "rkey" is omitted, server will generate it right?
198
+
"record": {
199
+
"$type": collection,
200
+
"subject": TARGET_DID,
201
+
"createdAt": Utc::now().to_rfc3339()
202
+
}
203
+
});
204
+
205
+
let create_res = client.post(format!("{}/xrpc/com.atproto.repo.createRecord", BASE_URL))
206
+
.bearer_auth(AUTH_TOKEN)
207
+
.json(&create_payload)
208
+
.send()
209
+
.await
210
+
.expect("Failed to send follow createRecord");
211
+
212
+
assert_eq!(create_res.status(), StatusCode::OK, "Failed to create follow record");
213
+
let create_body: Value = create_res.json().await.expect("create follow response was not JSON");
214
+
let follow_uri = create_body["uri"].as_str().expect("Response had no URI");
215
+
216
+
let rkey = follow_uri.split('/').last().expect("URI was malformed");
217
+
218
+
219
+
let params_get_follows = [
220
+
("actor", AUTH_DID),
221
+
];
222
+
let get_follows_res = client.get(format!("{}/xrpc/app.bsky.graph.getFollows", BASE_URL))
223
+
.query(¶ms_get_follows)
224
+
.bearer_auth(AUTH_TOKEN)
225
+
.send()
226
+
.await
227
+
.expect("Failed to send getFollows");
228
+
229
+
assert_eq!(get_follows_res.status(), StatusCode::OK, "getFollows did not return 200");
230
+
let get_follows_body: Value = get_follows_res.json().await.expect("getFollows response was not JSON");
231
+
232
+
let follows_list = get_follows_body["follows"].as_array().expect("follows key was not an array");
233
+
let is_following = follows_list.iter().any(|actor| {
234
+
actor["did"].as_str() == Some(TARGET_DID)
235
+
});
236
+
237
+
assert!(is_following, "getFollows list did not contain the target DID");
238
+
239
+
240
+
let delete_payload = json!({
241
+
"repo": AUTH_DID,
242
+
"collection": collection,
243
+
"rkey": rkey
244
+
});
245
+
246
+
let delete_res = client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
247
+
.bearer_auth(AUTH_TOKEN)
248
+
.json(&delete_payload)
249
+
.send()
250
+
.await
251
+
.expect("Failed to send unfollow deleteRecord");
252
+
253
+
assert_eq!(delete_res.status(), StatusCode::OK, "Failed to delete follow record");
254
+
255
+
256
+
let get_unfollowed_res = client.get(format!("{}/xrpc/app.bsky.graph.getFollows", BASE_URL))
257
+
.query(¶ms_get_follows)
258
+
.bearer_auth(AUTH_TOKEN)
259
+
.send()
260
+
.await
261
+
.expect("Failed to send getFollows after delete");
262
+
263
+
assert_eq!(get_unfollowed_res.status(), StatusCode::OK, "getFollows (after delete) did not return 200");
264
+
let get_unfollowed_body: Value = get_unfollowed_res.json().await.expect("getFollows (after delete) was not JSON");
265
+
266
+
let follows_list_after = get_unfollowed_body["follows"].as_array().expect("follows key was not an array");
267
+
let is_still_following = follows_list_after.iter().any(|actor| {
268
+
actor["did"].as_str() == Some(TARGET_DID)
269
+
});
270
+
271
+
assert!(!is_still_following, "getFollows list *still* contains the target DID after unfollow");
272
+
}
273
+
274
+
#[tokio::test]
275
+
async fn test_list_records_pagination() {
276
+
let client = client();
277
+
let collection = "app.bsky.feed.post";
278
+
let mut created_rkeys = Vec::new();
279
+
280
+
for i in 0..3 {
281
+
let rkey = format!("e2e_pagination_{}", Utc::now().timestamp_millis());
282
+
let payload = json!({
283
+
"repo": AUTH_DID,
284
+
"collection": collection,
285
+
"rkey": rkey,
286
+
"record": {
287
+
"$type": collection,
288
+
"text": format!("Pagination test post #{}", i),
289
+
"createdAt": Utc::now().to_rfc3339()
290
+
}
291
+
});
292
+
293
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
294
+
.bearer_auth(AUTH_TOKEN)
295
+
.json(&payload)
296
+
.send()
297
+
.await
298
+
.expect("Failed to create pagination post");
299
+
300
+
assert_eq!(res.status(), StatusCode::OK, "Failed to create post for pagination test");
301
+
created_rkeys.push(rkey);
302
+
tokio::time::sleep(Duration::from_millis(10)).await;
303
+
}
304
+
305
+
let params_page1 = [
306
+
("repo", AUTH_DID),
307
+
("collection", collection),
308
+
("limit", "2"),
309
+
];
310
+
311
+
let page1_res = client.get(format!("{}/xrpc/com.atproto.repo.listRecords", BASE_URL))
312
+
.query(¶ms_page1)
313
+
.send()
314
+
.await
315
+
.expect("Failed to send listRecords (page 1)");
316
+
317
+
assert_eq!(page1_res.status(), StatusCode::OK, "listRecords (page 1) failed");
318
+
let page1_body: Value = page1_res.json().await.expect("listRecords (page 1) was not JSON");
319
+
320
+
let page1_records = page1_body["records"].as_array().expect("records was not an array");
321
+
assert_eq!(page1_records.len(), 2, "Page 1 did not return 2 records");
322
+
323
+
let cursor = page1_body["cursor"].as_str().expect("Page 1 did not have a cursor");
324
+
325
+
326
+
let params_page2 = [
327
+
("repo", AUTH_DID),
328
+
("collection", collection),
329
+
("limit", "2"),
330
+
("cursor", cursor),
331
+
];
332
+
333
+
let page2_res = client.get(format!("{}/xrpc/com.atproto.repo.listRecords", BASE_URL))
334
+
.query(¶ms_page2)
335
+
.send()
336
+
.await
337
+
.expect("Failed to send listRecords (page 2)");
338
+
339
+
assert_eq!(page2_res.status(), StatusCode::OK, "listRecords (page 2) failed");
340
+
let page2_body: Value = page2_res.json().await.expect("listRecords (page 2) was not JSON");
341
+
342
+
let page2_records = page2_body["records"].as_array().expect("records was not an array");
343
+
assert_eq!(page2_records.len(), 1, "Page 2 did not return 1 record");
344
+
345
+
assert!(page2_body["cursor"].is_null() || page2_body["cursor"].as_str().is_none(), "Page 2 should not have a cursor");
346
+
347
+
348
+
for rkey in created_rkeys {
349
+
let delete_payload = json!({
350
+
"repo": AUTH_DID,
351
+
"collection": collection,
352
+
"rkey": rkey
353
+
});
354
+
client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
355
+
.bearer_auth(AUTH_TOKEN)
356
+
.json(&delete_payload)
357
+
.send()
358
+
.await
359
+
.expect("Failed to cleanup pagination post");
360
+
}
361
+
}
362
+
363
+
#[tokio::test]
364
+
async fn test_reply_thread_lifecycle() {
365
+
let client = client();
366
+
367
+
let (root_uri, root_cid, root_rkey) = create_test_post(
368
+
&client,
369
+
"This is the root of the thread",
370
+
None
371
+
).await;
372
+
373
+
374
+
let reply_ref = json!({
375
+
"root": { "uri": root_uri.clone(), "cid": root_cid.clone() },
376
+
"parent": { "uri": root_uri.clone(), "cid": root_cid.clone() }
377
+
});
378
+
379
+
let (reply_uri, _reply_cid, reply_rkey) = create_test_post(
380
+
&client,
381
+
"This is a reply!",
382
+
Some(reply_ref)
383
+
).await;
384
+
385
+
386
+
let params = [
387
+
("uri", &root_uri),
388
+
];
389
+
let res = client.get(format!("{}/xrpc/app.bsky.feed.getPostThread", BASE_URL))
390
+
.query(¶ms)
391
+
.bearer_auth(AUTH_TOKEN)
392
+
.send()
393
+
.await
394
+
.expect("Failed to send getPostThread");
395
+
396
+
assert_eq!(res.status(), StatusCode::OK, "getPostThread did not return 200");
397
+
let body: Value = res.json().await.expect("getPostThread response was not JSON");
398
+
399
+
assert_eq!(body["thread"]["$type"], "app.bsky.feed.defs#threadViewPost");
400
+
assert_eq!(body["thread"]["post"]["uri"], root_uri);
401
+
402
+
let replies = body["thread"]["replies"].as_array().expect("replies was not an array");
403
+
assert!(!replies.is_empty(), "Replies array is empty, but should contain the reply");
404
+
405
+
let found_reply = replies.iter().find(|r| {
406
+
r["post"]["uri"] == reply_uri
407
+
});
408
+
409
+
assert!(found_reply.is_some(), "Our specific reply was not found in the thread's replies");
410
+
411
+
412
+
let collection = "app.bsky.feed.post";
413
+
client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
414
+
.bearer_auth(AUTH_TOKEN)
415
+
.json(&json!({ "repo": AUTH_DID, "collection": collection, "rkey": reply_rkey }))
416
+
.send().await.expect("Failed to delete reply");
417
+
418
+
client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
419
+
.bearer_auth(AUTH_TOKEN)
420
+
.json(&json!({ "repo": AUTH_DID, "collection": collection, "rkey": root_rkey }))
421
+
.send().await.expect("Failed to delete root post");
422
+
}
423
+
424
+
#[tokio::test]
425
+
async fn test_account_journey_lifecycle() {
426
+
let client = client();
427
+
428
+
let ts = Utc::now().timestamp_millis();
429
+
let handle = format!("e2e-user-{}.test", ts);
430
+
let email = format!("e2e-user-{}@test.com", ts);
431
+
let password = "e2e-password-123";
432
+
433
+
let create_account_payload = json!({
434
+
"handle": handle,
435
+
"email": email,
436
+
"password": password
437
+
});
438
+
439
+
let create_res = client.post(format!("{}/xrpc/com.atproto.server.createAccount", BASE_URL))
440
+
.json(&create_account_payload)
441
+
.send()
442
+
.await
443
+
.expect("Failed to send createAccount");
444
+
445
+
assert_eq!(create_res.status(), StatusCode::OK, "Failed to create account");
446
+
let create_body: Value = create_res.json().await.expect("createAccount response was not JSON");
447
+
448
+
let new_did = create_body["did"].as_str().expect("Response had no DID").to_string();
449
+
let _new_jwt = create_body["accessJwt"].as_str().expect("Response had no accessJwt").to_string();
450
+
assert_eq!(create_body["handle"], handle);
451
+
452
+
453
+
let session_payload = json!({
454
+
"identifier": handle,
455
+
"password": password
456
+
});
457
+
458
+
let session_res = client.post(format!("{}/xrpc/com.atproto.server.createSession", BASE_URL))
459
+
.json(&session_payload)
460
+
.send()
461
+
.await
462
+
.expect("Failed to send createSession");
463
+
464
+
assert_eq!(session_res.status(), StatusCode::OK, "Failed to create session");
465
+
let session_body: Value = session_res.json().await.expect("createSession response was not JSON");
466
+
467
+
let session_jwt = session_body["accessJwt"].as_str().expect("Session response had no accessJwt").to_string();
468
+
assert_eq!(session_body["did"], new_did);
469
+
470
+
471
+
let profile_payload = json!({
472
+
"repo": new_did,
473
+
"collection": "app.bsky.actor.profile",
474
+
"rkey": "self", // The rkey for a profile is always "self"
475
+
"record": {
476
+
"$type": "app.bsky.actor.profile",
477
+
"displayName": "E2E Test User",
478
+
"description": "A user created by the e2e test suite."
479
+
}
480
+
});
481
+
482
+
let profile_res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
483
+
.bearer_auth(&session_jwt)
484
+
.json(&profile_payload)
485
+
.send()
486
+
.await
487
+
.expect("Failed to send putRecord for profile");
488
+
489
+
assert_eq!(profile_res.status(), StatusCode::OK, "Failed to create profile");
490
+
491
+
492
+
let params_get_profile = [
493
+
("actor", &handle),
494
+
];
495
+
let get_profile_res = client.get(format!("{}/xrpc/app.bsky.actor.getProfile", BASE_URL))
496
+
.query(¶ms_get_profile)
497
+
.send()
498
+
.await
499
+
.expect("Failed to send getProfile");
500
+
501
+
assert_eq!(get_profile_res.status(), StatusCode::OK, "getProfile did not return 200");
502
+
let profile_body: Value = get_profile_res.json().await.expect("getProfile response was not JSON");
503
+
504
+
assert_eq!(profile_body["did"], new_did);
505
+
assert_eq!(profile_body["handle"], handle);
506
+
assert_eq!(profile_body["displayName"], "E2E Test User");
507
+
508
+
509
+
let logout_res = client.post(format!("{}/xrpc/com.atproto.server.deleteSession", BASE_URL))
510
+
.bearer_auth(&session_jwt)
511
+
.send()
512
+
.await
513
+
.expect("Failed to send deleteSession");
514
+
515
+
assert_eq!(logout_res.status(), StatusCode::OK, "Failed to delete session");
516
+
517
+
518
+
let get_session_res = client.get(format!("{}/xrpc/com.atproto.server.getSession", BASE_URL))
519
+
.bearer_auth(&session_jwt)
520
+
.send()
521
+
.await
522
+
.expect("Failed to send getSession");
523
+
524
+
assert_eq!(get_session_res.status(), StatusCode::UNAUTHORIZED, "Session was still valid after logout");
525
+
}
526
+
527
+
async fn setup_new_user(handle_prefix: &str) -> (String, String) {
528
+
let client = client();
529
+
let ts = Utc::now().timestamp_millis();
530
+
let handle = format!("{}-{}.test", handle_prefix, ts);
531
+
let email = format!("{}-{}@test.com", handle_prefix, ts);
532
+
let password = "e2e-password-123";
533
+
534
+
let create_account_payload = json!({
535
+
"handle": handle,
536
+
"email": email,
537
+
"password": password
538
+
});
539
+
let create_res = client.post(format!("{}/xrpc/com.atproto.server.createAccount", BASE_URL))
540
+
.json(&create_account_payload)
541
+
.send()
542
+
.await
543
+
.expect("setup_new_user: Failed to send createAccount");
544
+
assert_eq!(create_res.status(), StatusCode::OK, "setup_new_user: Failed to create account");
545
+
let create_body: Value = create_res.json().await.expect("setup_new_user: createAccount response was not JSON");
546
+
547
+
let new_did = create_body["did"].as_str().expect("setup_new_user: Response had no DID").to_string();
548
+
let new_jwt = create_body["accessJwt"].as_str().expect("setup_new_user: Response had no accessJwt").to_string();
549
+
550
+
let profile_payload = json!({
551
+
"repo": new_did.clone(),
552
+
"collection": "app.bsky.actor.profile",
553
+
"rkey": "self",
554
+
"record": {
555
+
"$type": "app.bsky.actor.profile",
556
+
"displayName": format!("E2E User {}", handle),
557
+
"description": "A user created by the e2e test suite."
558
+
}
559
+
});
560
+
let profile_res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
561
+
.bearer_auth(&new_jwt)
562
+
.json(&profile_payload)
563
+
.send()
564
+
.await
565
+
.expect("setup_new_user: Failed to send putRecord for profile");
566
+
assert_eq!(profile_res.status(), StatusCode::OK, "setup_new_user: Failed to create profile");
567
+
568
+
(new_did, new_jwt)
569
+
}
570
+
571
+
async fn create_record_as(
572
+
client: &Client,
573
+
jwt: &str,
574
+
did: &str,
575
+
collection: &str,
576
+
record: Value,
577
+
) -> (String, String) {
578
+
let payload = json!({
579
+
"repo": did,
580
+
"collection": collection,
581
+
"record": record
582
+
});
583
+
584
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.createRecord", BASE_URL))
585
+
.bearer_auth(jwt)
586
+
.json(&payload)
587
+
.send()
588
+
.await
589
+
.expect("create_record_as: Failed to send createRecord");
590
+
591
+
assert_eq!(res.status(), StatusCode::OK, "create_record_as: Failed to create record");
592
+
let body: Value = res.json().await.expect("create_record_as: response was not JSON");
593
+
594
+
let uri = body["uri"].as_str().expect("create_record_as: Response had no URI").to_string();
595
+
let cid = body["cid"].as_str().expect("create_record_as: Response had no CID").to_string();
596
+
(uri, cid)
597
+
}
598
+
599
+
async fn delete_record_as(
600
+
client: &Client,
601
+
jwt: &str,
602
+
did: &str,
603
+
collection: &str,
604
+
rkey: &str,
605
+
) {
606
+
let payload = json!({
607
+
"repo": did,
608
+
"collection": collection,
609
+
"rkey": rkey
610
+
});
611
+
612
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
613
+
.bearer_auth(jwt)
614
+
.json(&payload)
615
+
.send()
616
+
.await
617
+
.expect("delete_record_as: Failed to send deleteRecord");
618
+
619
+
assert_eq!(res.status(), StatusCode::OK, "delete_record_as: Failed to delete record");
620
+
}
621
+
622
+
623
+
#[tokio::test]
624
+
async fn test_notification_lifecycle() {
625
+
let client = client();
626
+
627
+
let (user_a_did, user_a_jwt) = setup_new_user("user-a-notif").await;
628
+
let (user_b_did, user_b_jwt) = setup_new_user("user-b-notif").await;
629
+
630
+
let (post_uri, post_cid) = create_record_as(
631
+
&client,
632
+
&user_a_jwt,
633
+
&user_a_did,
634
+
"app.bsky.feed.post",
635
+
json!({
636
+
"$type": "app.bsky.feed.post",
637
+
"text": "A post to be notified about",
638
+
"createdAt": Utc::now().to_rfc3339()
639
+
}),
640
+
).await;
641
+
let post_ref = json!({ "uri": post_uri, "cid": post_cid });
642
+
643
+
let count_res_1 = client.get(format!("{}/xrpc/app.bsky.notification.getUnreadCount", BASE_URL))
644
+
.bearer_auth(&user_a_jwt)
645
+
.send().await.expect("getUnreadCount 1 failed");
646
+
let count_body_1: Value = count_res_1.json().await.expect("count 1 not json");
647
+
assert_eq!(count_body_1["count"], 0, "Initial unread count was not 0");
648
+
649
+
create_record_as(
650
+
&client, &user_b_jwt, &user_b_did,
651
+
"app.bsky.graph.follow",
652
+
json!({
653
+
"$type": "app.bsky.graph.follow",
654
+
"subject": user_a_did,
655
+
"createdAt": Utc::now().to_rfc3339()
656
+
}),
657
+
).await;
658
+
create_record_as(
659
+
&client, &user_b_jwt, &user_b_did,
660
+
"app.bsky.feed.like",
661
+
json!({
662
+
"$type": "app.bsky.feed.like",
663
+
"subject": post_ref,
664
+
"createdAt": Utc::now().to_rfc3339()
665
+
}),
666
+
).await;
667
+
create_record_as(
668
+
&client, &user_b_jwt, &user_b_did,
669
+
"app.bsky.feed.post",
670
+
json!({
671
+
"$type": "app.bsky.feed.post",
672
+
"text": "This is a reply!",
673
+
"reply": { "root": post_ref.clone(), "parent": post_ref.clone() },
674
+
"createdAt": Utc::now().to_rfc3339()
675
+
}),
676
+
).await;
677
+
678
+
tokio::time::sleep(Duration::from_millis(500)).await;
679
+
680
+
let count_res_2 = client.get(format!("{}/xrpc/app.bsky.notification.getUnreadCount", BASE_URL))
681
+
.bearer_auth(&user_a_jwt)
682
+
.send().await.expect("getUnreadCount 2 failed");
683
+
let count_body_2: Value = count_res_2.json().await.expect("count 2 not json");
684
+
assert_eq!(count_body_2["count"], 3, "Unread count was not 3 after actions");
685
+
686
+
let list_res = client.get(format!("{}/xrpc/app.bsky.notification.listNotifications", BASE_URL))
687
+
.bearer_auth(&user_a_jwt)
688
+
.send().await.expect("listNotifications failed");
689
+
let list_body: Value = list_res.json().await.expect("list not json");
690
+
691
+
let notifs = list_body["notifications"].as_array().expect("notifications not array");
692
+
assert_eq!(notifs.len(), 3, "Notification list did not have 3 items");
693
+
694
+
let has_follow = notifs.iter().any(|n| n["reason"] == "follow" && n["author"]["did"] == user_b_did);
695
+
let has_like = notifs.iter().any(|n| n["reason"] == "like" && n["author"]["did"] == user_b_did);
696
+
let has_reply = notifs.iter().any(|n| n["reason"] == "reply" && n["author"]["did"] == user_b_did);
697
+
698
+
assert!(has_follow, "Notification list missing 'follow'");
699
+
assert!(has_like, "Notification list missing 'like'");
700
+
assert!(has_reply, "Notification list missing 'reply'");
701
+
702
+
let count_res_3 = client.get(format!("{}/xrpc/app.bsky.notification.getUnreadCount", BASE_URL))
703
+
.bearer_auth(&user_a_jwt)
704
+
.send().await.expect("getUnreadCount 3 failed");
705
+
let count_body_3: Value = count_res_3.json().await.expect("count 3 not json");
706
+
assert_eq!(count_body_3["count"], 0, "Unread count was not 0 after list");
707
+
}
708
+
709
+
710
+
#[tokio::test]
711
+
async fn test_mute_lifecycle_filters_feed() {
712
+
let client = client();
713
+
714
+
let (user_a_did, user_a_jwt) = setup_new_user("user-a-mute").await;
715
+
let (user_b_did, user_b_jwt) = setup_new_user("user-b-mute").await;
716
+
717
+
let (post_uri, _) = create_record_as(
718
+
&client,
719
+
&user_b_jwt,
720
+
&user_b_did,
721
+
"app.bsky.feed.post",
722
+
json!({
723
+
"$type": "app.bsky.feed.post",
724
+
"text": "A post from User B",
725
+
"createdAt": Utc::now().to_rfc3339()
726
+
}),
727
+
).await;
728
+
729
+
let feed_params_1 = [("actor", &user_b_did)];
730
+
let feed_res_1 = client.get(format!("{}/xrpc/app.bsky.feed.getAuthorFeed", BASE_URL))
731
+
.query(&feed_params_1)
732
+
.bearer_auth(&user_a_jwt)
733
+
.send().await.expect("getAuthorFeed 1 failed");
734
+
let feed_body_1: Value = feed_res_1.json().await.expect("feed 1 not json");
735
+
736
+
let feed_1 = feed_body_1["feed"].as_array().expect("feed 1 not array");
737
+
let found_post_1 = feed_1.iter().any(|p| p["post"]["uri"] == post_uri);
738
+
assert!(found_post_1, "User B's post was not in their feed before mute");
739
+
740
+
let (mute_uri, _) = create_record_as(
741
+
&client, &user_a_jwt, &user_a_did,
742
+
"app.bsky.graph.mute",
743
+
json!({
744
+
"$type": "app.bsky.graph.mute",
745
+
"subject": user_b_did,
746
+
"createdAt": Utc::now().to_rfc3339()
747
+
}),
748
+
).await;
749
+
let mute_rkey = mute_uri.split('/').last().unwrap();
750
+
751
+
let feed_params_2 = [("actor", &user_b_did)];
752
+
let feed_res_2 = client.get(format!("{}/xrpc/app.bsky.feed.getAuthorFeed", BASE_URL))
753
+
.query(&feed_params_2)
754
+
.bearer_auth(&user_a_jwt)
755
+
.send().await.expect("getAuthorFeed 2 failed");
756
+
let feed_body_2: Value = feed_res_2.json().await.expect("feed 2 not json");
757
+
758
+
let feed_2 = feed_body_2["feed"].as_array().expect("feed 2 not array");
759
+
assert!(feed_2.is_empty(), "User B's feed was not empty after mute");
760
+
761
+
delete_record_as(
762
+
&client, &user_a_jwt, &user_a_did,
763
+
"app.bsky.graph.mute",
764
+
mute_rkey,
765
+
).await;
766
+
767
+
let feed_params_3 = [("actor", &user_b_did)];
768
+
let feed_res_3 = client.get(format!("{}/xrpc/app.bsky.feed.getAuthorFeed", BASE_URL))
769
+
.query(&feed_params_3)
770
+
.bearer_auth(&user_a_jwt)
771
+
.send().await.expect("getAuthorFeed 3 failed");
772
+
let feed_body_3: Value = feed_res_3.json().await.expect("feed 3 not json");
773
+
774
+
let feed_3 = feed_body_3["feed"].as_array().expect("feed 3 not array");
775
+
let found_post_3 = feed_3.iter().any(|p| p["post"]["uri"] == post_uri);
776
+
assert!(found_post_3, "User B's post did not reappear after unmute");
777
+
}
778
+
779
+
780
+
#[tokio::test]
781
+
async fn test_record_update_conflict_lifecycle() {
782
+
let client = client();
783
+
784
+
let (user_did, user_jwt) = setup_new_user("user-conflict").await;
785
+
786
+
let get_res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
787
+
.query(&[
788
+
("repo", &user_did),
789
+
("collection", &"app.bsky.actor.profile".to_string()),
790
+
("rkey", &"self".to_string()),
791
+
])
792
+
.send().await.expect("getRecord failed");
793
+
let get_body: Value = get_res.json().await.expect("getRecord not json");
794
+
let cid_v1 = get_body["cid"].as_str().expect("Profile v1 had no CID").to_string();
795
+
796
+
let update_payload_v2 = json!({
797
+
"repo": user_did,
798
+
"collection": "app.bsky.actor.profile",
799
+
"rkey": "self",
800
+
"record": {
801
+
"$type": "app.bsky.actor.profile",
802
+
"displayName": "Updated Name (v2)"
803
+
},
804
+
"swapCommit": cid_v1 // <-- Correctly point to v1
805
+
});
806
+
let update_res_v2 = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
807
+
.bearer_auth(&user_jwt)
808
+
.json(&update_payload_v2)
809
+
.send().await.expect("putRecord v2 failed");
810
+
assert_eq!(update_res_v2.status(), StatusCode::OK, "v2 update failed");
811
+
let update_body_v2: Value = update_res_v2.json().await.expect("v2 body not json");
812
+
let cid_v2 = update_body_v2["cid"].as_str().expect("v2 response had no CID").to_string();
813
+
814
+
let update_payload_v3_stale = json!({
815
+
"repo": user_did,
816
+
"collection": "app.bsky.actor.profile",
817
+
"rkey": "self",
818
+
"record": {
819
+
"$type": "app.bsky.actor.profile",
820
+
"displayName": "Stale Update (v3)"
821
+
},
822
+
"swapCommit": cid_v1
823
+
});
824
+
let update_res_v3_stale = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
825
+
.bearer_auth(&user_jwt)
826
+
.json(&update_payload_v3_stale)
827
+
.send().await.expect("putRecord v3 (stale) failed");
828
+
829
+
assert_eq!(
830
+
update_res_v3_stale.status(),
831
+
StatusCode::CONFLICT,
832
+
"Stale update did not cause a 409 Conflict"
833
+
);
834
+
835
+
let update_payload_v3_good = json!({
836
+
"repo": user_did,
837
+
"collection": "app.bsky.actor.profile",
838
+
"rkey": "self",
839
+
"record": {
840
+
"$type": "app.bsky.actor.profile",
841
+
"displayName": "Good Update (v3)"
842
+
},
843
+
"swapCommit": cid_v2 // <-- Correct
844
+
});
845
+
let update_res_v3_good = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
846
+
.bearer_auth(&user_jwt)
847
+
.json(&update_payload_v3_good)
848
+
.send().await.expect("putRecord v3 (good) failed");
849
+
850
+
assert_eq!(update_res_v3_good.status(), StatusCode::OK, "v3 (good) update failed");
851
+
}
852
+
853
+
854
+
#[tokio::test]
855
+
async fn test_complex_thread_deletion_lifecycle() {
856
+
let client = client();
857
+
858
+
let (user_a_did, user_a_jwt) = setup_new_user("user-a-thread").await;
859
+
let (user_b_did, user_b_jwt) = setup_new_user("user-b-thread").await;
860
+
let (user_c_did, user_c_jwt) = setup_new_user("user-c-thread").await;
861
+
862
+
let (p1_uri, p1_cid) = create_record_as(
863
+
&client, &user_a_jwt, &user_a_did,
864
+
"app.bsky.feed.post",
865
+
json!({
866
+
"$type": "app.bsky.feed.post",
867
+
"text": "P1 (Root)",
868
+
"createdAt": Utc::now().to_rfc3339()
869
+
}),
870
+
).await;
871
+
let p1_ref = json!({ "uri": p1_uri.clone(), "cid": p1_cid.clone() });
872
+
873
+
let (p2_uri, p2_cid) = create_record_as(
874
+
&client, &user_b_jwt, &user_b_did,
875
+
"app.bsky.feed.post",
876
+
json!({
877
+
"$type": "app.bsky.feed.post",
878
+
"text": "P2 (Reply)",
879
+
"reply": { "root": p1_ref.clone(), "parent": p1_ref.clone() },
880
+
"createdAt": Utc::now().to_rfc3339()
881
+
}),
882
+
).await;
883
+
let p2_ref = json!({ "uri": p2_uri.clone(), "cid": p2_cid.clone() });
884
+
let p2_rkey = p2_uri.split('/').last().unwrap().to_string();
885
+
886
+
let (p3_uri, _) = create_record_as(
887
+
&client, &user_c_jwt, &user_c_did,
888
+
"app.bsky.feed.post",
889
+
json!({
890
+
"$type": "app.bsky.feed.post",
891
+
"text": "P3 (Grandchild)",
892
+
"reply": { "root": p1_ref.clone(), "parent": p2_ref.clone() },
893
+
"createdAt": Utc::now().to_rfc3339()
894
+
}),
895
+
).await;
896
+
897
+
let thread_res_1 = client.get(format!("{}/xrpc/app.bsky.feed.getPostThread", BASE_URL))
898
+
.query(&[("uri", &p1_uri)])
899
+
.bearer_auth(&user_a_jwt)
900
+
.send().await.expect("getThread 1 failed");
901
+
let thread_body_1: Value = thread_res_1.json().await.expect("thread 1 not json");
902
+
903
+
let p1_replies = thread_body_1["thread"]["replies"].as_array().unwrap();
904
+
assert_eq!(p1_replies.len(), 1, "P1 should have 1 reply");
905
+
assert_eq!(p1_replies[0]["post"]["uri"], p2_uri, "P1's reply is not P2");
906
+
907
+
let p2_replies = p1_replies[0]["replies"].as_array().unwrap();
908
+
assert_eq!(p2_replies.len(), 1, "P2 should have 1 reply");
909
+
assert_eq!(p2_replies[0]["post"]["uri"], p3_uri, "P2's reply is not P3");
910
+
911
+
delete_record_as(
912
+
&client, &user_b_jwt, &user_b_did,
913
+
"app.bsky.feed.post",
914
+
&p2_rkey,
915
+
).await;
916
+
917
+
let thread_res_2 = client.get(format!("{}/xrpc/app.bsky.feed.getPostThread", BASE_URL))
918
+
.query(&[("uri", &p1_uri)])
919
+
.bearer_auth(&user_a_jwt)
920
+
.send().await.expect("getThread 2 failed");
921
+
let thread_body_2: Value = thread_res_2.json().await.expect("thread 2 not json");
922
+
923
+
let p1_replies_2 = thread_body_2["thread"]["replies"].as_array().unwrap();
924
+
assert_eq!(p1_replies_2.len(), 1, "P1 should still have 1 reply (the deleted one)");
925
+
926
+
let deleted_post = &p1_replies_2[0];
927
+
assert_eq!(
928
+
deleted_post["$type"], "app.bsky.feed.defs#notFoundPost",
929
+
"P2 did not appear as a notFoundPost"
930
+
);
931
+
assert_eq!(deleted_post["uri"], p2_uri, "notFoundPost URI does not match P2");
932
+
933
+
let p3_reply = deleted_post["replies"].as_array().unwrap();
934
+
assert_eq!(p3_reply.len(), 1, "notFoundPost should still have P3 as a reply");
935
+
assert_eq!(p3_reply[0]["post"]["uri"], p3_uri, "The reply to the deleted post is not P3");
936
+
}
+31
tests/notification.rs
+31
tests/notification.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
use reqwest::StatusCode;
4
+
5
+
#[tokio::test]
6
+
async fn test_list_notifications() {
7
+
let client = client();
8
+
let params = [
9
+
("limit", "30"),
10
+
];
11
+
let res = client.get(format!("{}/xrpc/app.bsky.notification.listNotifications", BASE_URL))
12
+
.query(¶ms)
13
+
.bearer_auth(AUTH_TOKEN)
14
+
.send()
15
+
.await
16
+
.expect("Failed to send request");
17
+
18
+
assert_eq!(res.status(), StatusCode::OK);
19
+
}
20
+
21
+
#[tokio::test]
22
+
async fn test_get_unread_count() {
23
+
let client = client();
24
+
let res = client.get(format!("{}/xrpc/app.bsky.notification.getUnreadCount", BASE_URL))
25
+
.bearer_auth(AUTH_TOKEN)
26
+
.send()
27
+
.await
28
+
.expect("Failed to send request");
29
+
30
+
assert_eq!(res.status(), StatusCode::OK);
31
+
}
+354
tests/repo.rs
+354
tests/repo.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
4
+
use reqwest::{header, StatusCode};
5
+
use serde_json::{json, Value};
6
+
use chrono::Utc;
7
+
8
+
#[tokio::test]
9
+
#[ignore]
10
+
async fn test_get_record() {
11
+
let client = client();
12
+
let params = [
13
+
("repo", "did:plc:12345"),
14
+
("collection", "app.bsky.actor.profile"),
15
+
("rkey", "self"),
16
+
];
17
+
18
+
let res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
19
+
.query(¶ms)
20
+
.send()
21
+
.await
22
+
.expect("Failed to send request");
23
+
24
+
assert_eq!(res.status(), StatusCode::OK);
25
+
let body: Value = res.json().await.expect("Response was not valid JSON");
26
+
assert_eq!(body["value"]["$type"], "app.bsky.actor.profile");
27
+
}
28
+
29
+
#[tokio::test]
30
+
#[ignore]
31
+
async fn test_get_record_not_found() {
32
+
let client = client();
33
+
let params = [
34
+
("repo", "did:plc:12345"),
35
+
("collection", "app.bsky.feed.post"),
36
+
("rkey", "nonexistent"),
37
+
];
38
+
39
+
let res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
40
+
.query(¶ms)
41
+
.send()
42
+
.await
43
+
.expect("Failed to send request");
44
+
45
+
assert_eq!(res.status(), StatusCode::NOT_FOUND);
46
+
let body: Value = res.json().await.expect("Response was not valid JSON");
47
+
assert_eq!(body["error"], "NotFound");
48
+
}
49
+
50
+
#[tokio::test]
51
+
#[ignore]
52
+
async fn test_upload_blob_no_auth() {
53
+
let client = client();
54
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.uploadBlob", BASE_URL))
55
+
.header(header::CONTENT_TYPE, "text/plain")
56
+
.body("no auth")
57
+
.send()
58
+
.await
59
+
.expect("Failed to send request");
60
+
61
+
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
62
+
let body: Value = res.json().await.expect("Response was not valid JSON");
63
+
assert_eq!(body["error"], "AuthenticationFailed");
64
+
}
65
+
66
+
#[tokio::test]
67
+
#[ignore]
68
+
async fn test_upload_blob_success() {
69
+
let client = client();
70
+
let (token, _) = create_account_and_login(&client).await;
71
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.uploadBlob", BASE_URL))
72
+
.header(header::CONTENT_TYPE, "text/plain")
73
+
.bearer_auth(token)
74
+
.body("This is our blob data")
75
+
.send()
76
+
.await
77
+
.expect("Failed to send request");
78
+
79
+
assert_eq!(res.status(), StatusCode::OK);
80
+
let body: Value = res.json().await.expect("Response was not valid JSON");
81
+
assert!(body["blob"]["ref"]["$link"].as_str().is_some());
82
+
}
83
+
84
+
#[tokio::test]
85
+
#[ignore]
86
+
async fn test_put_record_no_auth() {
87
+
let client = client();
88
+
let payload = json!({
89
+
"repo": "did:plc:123",
90
+
"collection": "app.bsky.feed.post",
91
+
"rkey": "fake",
92
+
"record": {}
93
+
});
94
+
95
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
96
+
.json(&payload)
97
+
.send()
98
+
.await
99
+
.expect("Failed to send request");
100
+
101
+
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
102
+
let body: Value = res.json().await.expect("Response was not valid JSON");
103
+
assert_eq!(body["error"], "AuthenticationFailed");
104
+
}
105
+
106
+
#[tokio::test]
107
+
#[ignore]
108
+
async fn test_put_record_success() {
109
+
let client = client();
110
+
let (token, did) = create_account_and_login(&client).await;
111
+
let now = Utc::now().to_rfc3339();
112
+
let payload = json!({
113
+
"repo": did,
114
+
"collection": "app.bsky.feed.post",
115
+
"rkey": "e2e_test_post",
116
+
"record": {
117
+
"$type": "app.bsky.feed.post",
118
+
"text": "Hello from the e2e test script!",
119
+
"createdAt": now
120
+
}
121
+
});
122
+
123
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
124
+
.bearer_auth(token)
125
+
.json(&payload)
126
+
.send()
127
+
.await
128
+
.expect("Failed to send request");
129
+
130
+
assert_eq!(res.status(), StatusCode::OK);
131
+
let body: Value = res.json().await.expect("Response was not valid JSON");
132
+
assert!(body.get("uri").is_some());
133
+
assert!(body.get("cid").is_some());
134
+
}
135
+
136
+
#[tokio::test]
137
+
#[ignore]
138
+
async fn test_get_record_missing_params() {
139
+
let client = client();
140
+
// Missing `collection` and `rkey`
141
+
let params = [
142
+
("repo", "did:plc:12345"),
143
+
];
144
+
145
+
let res = client.get(format!("{}/xrpc/com.atproto.repo.getRecord", BASE_URL))
146
+
.query(¶ms)
147
+
.send()
148
+
.await
149
+
.expect("Failed to send request");
150
+
151
+
// This will fail (get 404) until the handler validates query params
152
+
assert_eq!(res.status(), StatusCode::BAD_REQUEST, "Expected 400 for missing params");
153
+
}
154
+
155
+
#[tokio::test]
156
+
#[ignore]
157
+
async fn test_upload_blob_bad_token() {
158
+
let client = client();
159
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.uploadBlob", BASE_URL))
160
+
.header(header::CONTENT_TYPE, "text/plain")
161
+
.bearer_auth(BAD_AUTH_TOKEN)
162
+
.body("This is our blob data")
163
+
.send()
164
+
.await
165
+
.expect("Failed to send request");
166
+
167
+
// This *should* pass if the auth stub is working correctly
168
+
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
169
+
let body: Value = res.json().await.expect("Response was not valid JSON");
170
+
assert_eq!(body["error"], "AuthenticationFailed");
171
+
}
172
+
173
+
#[tokio::test]
174
+
#[ignore]
175
+
async fn test_put_record_mismatched_repo() {
176
+
let client = client();
177
+
let (token, _) = create_account_and_login(&client).await;
178
+
let now = Utc::now().to_rfc3339();
179
+
let payload = json!({
180
+
"repo": "did:plc:OTHER-USER", // This does NOT match AUTH_DID
181
+
"collection": "app.bsky.feed.post",
182
+
"rkey": "e2e_test_post",
183
+
"record": {
184
+
"$type": "app.bsky.feed.post",
185
+
"text": "Hello from the e2e test script!",
186
+
"createdAt": now
187
+
}
188
+
});
189
+
190
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
191
+
.bearer_auth(token)
192
+
.json(&payload)
193
+
.send()
194
+
.await
195
+
.expect("Failed to send request");
196
+
197
+
// This will fail (get 200) until handler validates repo matches auth
198
+
assert_eq!(res.status(), StatusCode::FORBIDDEN, "Expected 403 for mismatched repo and auth");
199
+
}
200
+
201
+
#[tokio::test]
202
+
#[ignore]
203
+
async fn test_put_record_invalid_schema() {
204
+
let client = client();
205
+
let (token, did) = create_account_and_login(&client).await;
206
+
let now = Utc::now().to_rfc3339();
207
+
let payload = json!({
208
+
"repo": did,
209
+
"collection": "app.bsky.feed.post",
210
+
"rkey": "e2e_test_invalid",
211
+
"record": {
212
+
"$type": "app.bsky.feed.post",
213
+
// "text" field is missing, this is invalid
214
+
"createdAt": now
215
+
}
216
+
});
217
+
218
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.putRecord", BASE_URL))
219
+
.bearer_auth(token)
220
+
.json(&payload)
221
+
.send()
222
+
.await
223
+
.expect("Failed to send request");
224
+
225
+
// This will fail (get 200) until handler validates record schema
226
+
assert_eq!(res.status(), StatusCode::BAD_REQUEST, "Expected 400 for invalid record schema");
227
+
}
228
+
229
+
#[tokio::test]
230
+
#[ignore]
231
+
async fn test_upload_blob_unsupported_mime_type() {
232
+
let client = client();
233
+
let (token, _) = create_account_and_login(&client).await;
234
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.uploadBlob", BASE_URL))
235
+
.header(header::CONTENT_TYPE, "application/xml")
236
+
.bearer_auth(token)
237
+
.body("<xml>not an image</xml>")
238
+
.send()
239
+
.await
240
+
.expect("Failed to send request");
241
+
242
+
// This will fail (get 200) until handler validates mime type
243
+
assert_eq!(res.status(), StatusCode::BAD_REQUEST, "Expected 400 for unsupported mime type");
244
+
}
245
+
246
+
#[tokio::test]
247
+
async fn test_list_records() {
248
+
let client = client();
249
+
let (_, did) = create_account_and_login(&client).await;
250
+
let params = [
251
+
("repo", did.as_str()),
252
+
("collection", "app.bsky.feed.post"),
253
+
("limit", "10"),
254
+
];
255
+
let res = client.get(format!("{}/xrpc/com.atproto.repo.listRecords", BASE_URL))
256
+
.query(¶ms)
257
+
.send()
258
+
.await
259
+
.expect("Failed to send request");
260
+
261
+
assert_eq!(res.status(), StatusCode::OK);
262
+
}
263
+
264
+
#[tokio::test]
265
+
async fn test_delete_record() {
266
+
let client = client();
267
+
let (token, did) = create_account_and_login(&client).await;
268
+
let payload = json!({
269
+
"repo": did,
270
+
"collection": "app.bsky.feed.post",
271
+
"rkey": "some_post_to_delete"
272
+
});
273
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.deleteRecord", BASE_URL))
274
+
.bearer_auth(token)
275
+
.json(&payload)
276
+
.send()
277
+
.await
278
+
.expect("Failed to send request");
279
+
280
+
assert_eq!(res.status(), StatusCode::OK);
281
+
}
282
+
283
+
#[tokio::test]
284
+
async fn test_describe_repo() {
285
+
let client = client();
286
+
let (_, did) = create_account_and_login(&client).await;
287
+
let params = [
288
+
("repo", did.as_str()),
289
+
];
290
+
let res = client.get(format!("{}/xrpc/com.atproto.repo.describeRepo", BASE_URL))
291
+
.query(¶ms)
292
+
.send()
293
+
.await
294
+
.expect("Failed to send request");
295
+
296
+
assert_eq!(res.status(), StatusCode::OK);
297
+
}
298
+
299
+
#[tokio::test]
300
+
async fn test_create_record_success_with_generated_rkey() {
301
+
let client = client();
302
+
let (token, did) = create_account_and_login(&client).await;
303
+
let payload = json!({
304
+
"repo": did,
305
+
"collection": "app.bsky.feed.post",
306
+
"record": {
307
+
"$type": "app.bsky.feed.post",
308
+
"text": "Hello, world!",
309
+
"createdAt": "2025-12-02T12:00:00Z"
310
+
}
311
+
});
312
+
313
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.createRecord", BASE_URL))
314
+
.json(&payload)
315
+
.bearer_auth(token) // Assuming auth is required
316
+
.send()
317
+
.await
318
+
.expect("Failed to send request");
319
+
320
+
assert_eq!(res.status(), StatusCode::OK);
321
+
let body: Value = res.json().await.expect("Response was not valid JSON");
322
+
let uri = body["uri"].as_str().unwrap();
323
+
assert!(uri.starts_with(&format!("at://{}/app.bsky.feed.post/", did)));
324
+
// assert_eq!(body["cid"], "bafyreihy"); // CID is now real
325
+
}
326
+
327
+
#[tokio::test]
328
+
async fn test_create_record_success_with_provided_rkey() {
329
+
let client = client();
330
+
let (token, did) = create_account_and_login(&client).await;
331
+
let rkey = "custom-rkey";
332
+
let payload = json!({
333
+
"repo": did,
334
+
"collection": "app.bsky.feed.post",
335
+
"rkey": rkey,
336
+
"record": {
337
+
"$type": "app.bsky.feed.post",
338
+
"text": "Hello, world!",
339
+
"createdAt": "2025-12-02T12:00:00Z"
340
+
}
341
+
});
342
+
343
+
let res = client.post(format!("{}/xrpc/com.atproto.repo.createRecord", BASE_URL))
344
+
.json(&payload)
345
+
.bearer_auth(token) // Assuming auth is required
346
+
.send()
347
+
.await
348
+
.expect("Failed to send request");
349
+
350
+
assert_eq!(res.status(), StatusCode::OK);
351
+
let body: Value = res.json().await.expect("Response was not valid JSON");
352
+
assert_eq!(body["uri"], format!("at://{}/app.bsky.feed.post/{}", did, rkey));
353
+
// assert_eq!(body["cid"], "bafyreihy"); // CID is now real
354
+
}
+164
tests/server.rs
+164
tests/server.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
4
+
use reqwest::StatusCode;
5
+
use serde_json::{json, Value};
6
+
7
+
#[tokio::test]
8
+
async fn test_health() {
9
+
let client = client();
10
+
let res = client.get(format!("{}/health", BASE_URL))
11
+
.send()
12
+
.await
13
+
.expect("Failed to send request");
14
+
15
+
assert_eq!(res.status(), StatusCode::OK);
16
+
assert_eq!(res.text().await.unwrap(), "OK");
17
+
}
18
+
19
+
#[tokio::test]
20
+
async fn test_describe_server() {
21
+
let client = client();
22
+
let res = client.get(format!("{}/xrpc/com.atproto.server.describeServer", BASE_URL))
23
+
.send()
24
+
.await
25
+
.expect("Failed to send request");
26
+
27
+
assert_eq!(res.status(), StatusCode::OK);
28
+
let body: Value = res.json().await.expect("Response was not valid JSON");
29
+
assert!(body.get("availableUserDomains").is_some());
30
+
}
31
+
32
+
#[tokio::test]
33
+
async fn test_create_session() {
34
+
let client = client();
35
+
36
+
let handle = format!("user_{}", uuid::Uuid::new_v4());
37
+
let payload = json!({
38
+
"handle": handle,
39
+
"email": format!("{}@example.com", handle),
40
+
"password": "password"
41
+
});
42
+
let _ = client.post(format!("{}/xrpc/com.atproto.server.createAccount", BASE_URL))
43
+
.json(&payload)
44
+
.send()
45
+
.await;
46
+
47
+
let payload = json!({
48
+
"identifier": handle,
49
+
"password": "password"
50
+
});
51
+
52
+
let res = client.post(format!("{}/xrpc/com.atproto.server.createSession", BASE_URL))
53
+
.json(&payload)
54
+
.send()
55
+
.await
56
+
.expect("Failed to send request");
57
+
58
+
assert_eq!(res.status(), StatusCode::OK);
59
+
let body: Value = res.json().await.expect("Response was not valid JSON");
60
+
assert!(body.get("accessJwt").is_some());
61
+
}
62
+
63
+
#[tokio::test]
64
+
async fn test_create_session_missing_identifier() {
65
+
let client = client();
66
+
let payload = json!({
67
+
"password": "password"
68
+
});
69
+
70
+
let res = client.post(format!("{}/xrpc/com.atproto.server.createSession", BASE_URL))
71
+
.json(&payload)
72
+
.send()
73
+
.await
74
+
.expect("Failed to send request");
75
+
76
+
assert!(res.status() == StatusCode::BAD_REQUEST || res.status() == StatusCode::UNPROCESSABLE_ENTITY,
77
+
"Expected 400 or 422 for missing identifier, got {}", res.status());
78
+
}
79
+
80
+
#[tokio::test]
81
+
async fn test_create_account_invalid_handle() {
82
+
let client = client();
83
+
let payload = json!({
84
+
"handle": "invalid!handle.com",
85
+
"email": "test@example.com",
86
+
"password": "password"
87
+
});
88
+
89
+
let res = client.post(format!("{}/xrpc/com.atproto.server.createAccount", BASE_URL))
90
+
.json(&payload)
91
+
.send()
92
+
.await
93
+
.expect("Failed to send request");
94
+
95
+
assert_eq!(res.status(), StatusCode::BAD_REQUEST, "Expected 400 for invalid handle chars");
96
+
}
97
+
98
+
#[tokio::test]
99
+
async fn test_get_session() {
100
+
let client = client();
101
+
let res = client.get(format!("{}/xrpc/com.atproto.server.getSession", BASE_URL))
102
+
.bearer_auth(AUTH_TOKEN)
103
+
.send()
104
+
.await
105
+
.expect("Failed to send request");
106
+
107
+
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
108
+
}
109
+
110
+
#[tokio::test]
111
+
async fn test_refresh_session() {
112
+
let client = client();
113
+
114
+
let handle = format!("refresh_user_{}", uuid::Uuid::new_v4());
115
+
let payload = json!({
116
+
"handle": handle,
117
+
"email": format!("{}@example.com", handle),
118
+
"password": "password"
119
+
});
120
+
let _ = client.post(format!("{}/xrpc/com.atproto.server.createAccount", BASE_URL))
121
+
.json(&payload)
122
+
.send()
123
+
.await;
124
+
125
+
let login_payload = json!({
126
+
"identifier": handle,
127
+
"password": "password"
128
+
});
129
+
let res = client.post(format!("{}/xrpc/com.atproto.server.createSession", BASE_URL))
130
+
.json(&login_payload)
131
+
.send()
132
+
.await
133
+
.expect("Failed to login");
134
+
135
+
assert_eq!(res.status(), StatusCode::OK);
136
+
let body: Value = res.json().await.expect("Invalid JSON");
137
+
let refresh_jwt = body["refreshJwt"].as_str().expect("No refreshJwt").to_string();
138
+
let access_jwt = body["accessJwt"].as_str().expect("No accessJwt").to_string();
139
+
140
+
let res = client.post(format!("{}/xrpc/com.atproto.server.refreshSession", BASE_URL))
141
+
.bearer_auth(&refresh_jwt)
142
+
.send()
143
+
.await
144
+
.expect("Failed to refresh");
145
+
146
+
assert_eq!(res.status(), StatusCode::OK);
147
+
let body: Value = res.json().await.expect("Invalid JSON");
148
+
assert!(body["accessJwt"].as_str().is_some());
149
+
assert!(body["refreshJwt"].as_str().is_some());
150
+
assert_ne!(body["accessJwt"].as_str().unwrap(), access_jwt);
151
+
assert_ne!(body["refreshJwt"].as_str().unwrap(), refresh_jwt);
152
+
}
153
+
154
+
#[tokio::test]
155
+
async fn test_delete_session() {
156
+
let client = client();
157
+
let res = client.post(format!("{}/xrpc/com.atproto.server.deleteSession", BASE_URL))
158
+
.bearer_auth(AUTH_TOKEN)
159
+
.send()
160
+
.await
161
+
.expect("Failed to send request");
162
+
163
+
assert_eq!(res.status(), StatusCode::UNAUTHORIZED);
164
+
}
+34
tests/sync.rs
+34
tests/sync.rs
···
···
1
+
mod common;
2
+
use common::*;
3
+
use reqwest::StatusCode;
4
+
5
+
#[tokio::test]
6
+
async fn test_get_repo() {
7
+
let client = client();
8
+
let params = [
9
+
("did", AUTH_DID),
10
+
];
11
+
let res = client.get(format!("{}/xrpc/com.atproto.sync.getRepo", BASE_URL))
12
+
.query(¶ms)
13
+
.send()
14
+
.await
15
+
.expect("Failed to send request");
16
+
17
+
assert_eq!(res.status(), StatusCode::OK);
18
+
}
19
+
20
+
#[tokio::test]
21
+
async fn test_get_blocks() {
22
+
let client = client();
23
+
let params = [
24
+
("did", AUTH_DID),
25
+
// "cids" would be a list of CIDs
26
+
];
27
+
let res = client.get(format!("{}/xrpc/com.atproto.sync.getBlocks", BASE_URL))
28
+
.query(¶ms)
29
+
.send()
30
+
.await
31
+
.expect("Failed to send request");
32
+
33
+
assert_eq!(res.status(), StatusCode::OK);
34
+
}