Constellation, Spacedust, Slingshot, UFOs: atproto crates and services for microcosm

reflector: an any-domain did:web->service mapper

Changed files
+147 -45
reflector
+34 -44
Cargo.lock
··· 989 989 990 990 [[package]] 991 991 name = "clap" 992 - version = "4.5.46" 992 + version = "4.5.47" 993 993 source = "registry+https://github.com/rust-lang/crates.io-index" 994 - checksum = "2c5e4fcf9c21d2e544ca1ee9d8552de13019a42aa7dbf32747fa7aaf1df76e57" 994 + checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" 995 995 dependencies = [ 996 996 "clap_builder", 997 997 "clap_derive", ··· 999 999 1000 1000 [[package]] 1001 1001 name = "clap_builder" 1002 - version = "4.5.46" 1002 + version = "4.5.47" 1003 1003 source = "registry+https://github.com/rust-lang/crates.io-index" 1004 - checksum = "fecb53a0e6fcfb055f686001bc2e2592fa527efaf38dbe81a6a9563562e57d41" 1004 + checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" 1005 1005 dependencies = [ 1006 1006 "anstream", 1007 1007 "anstyle", ··· 1011 1011 1012 1012 [[package]] 1013 1013 name = "clap_derive" 1014 - version = "4.5.45" 1014 + version = "4.5.47" 1015 1015 source = "registry+https://github.com/rust-lang/crates.io-index" 1016 - checksum = "14cb31bb0a7d536caef2639baa7fad459e15c3144efefa6dbd1c84562c4739f6" 1016 + checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" 1017 1017 dependencies = [ 1018 1018 "heck", 1019 1019 "proc-macro2", ··· 3148 3148 3149 3149 [[package]] 3150 3150 name = "log" 3151 - version = "0.4.27" 3151 + version = "0.4.28" 3152 3152 source = "registry+https://github.com/rust-lang/crates.io-index" 3153 - checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" 3153 + checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" 3154 3154 3155 3155 [[package]] 3156 3156 name = "loom" ··· 3300 3300 3301 3301 [[package]] 3302 3302 name = "matchers" 3303 - version = "0.1.0" 3303 + version = "0.2.0" 3304 3304 source = "registry+https://github.com/rust-lang/crates.io-index" 3305 - checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" 3305 + checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" 3306 3306 dependencies = [ 3307 - "regex-automata 0.1.10", 3307 + "regex-automata", 3308 3308 ] 3309 3309 3310 3310 [[package]] ··· 3603 3603 3604 3604 [[package]] 3605 3605 name = "nu-ansi-term" 3606 - version = "0.46.0" 3606 + version = "0.50.1" 3607 3607 source = "registry+https://github.com/rust-lang/crates.io-index" 3608 - checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" 3608 + checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" 3609 3609 dependencies = [ 3610 - "overload", 3611 - "winapi", 3610 + "windows-sys 0.52.0", 3612 3611 ] 3613 3612 3614 3613 [[package]] ··· 3809 3808 dependencies = [ 3810 3809 "hashbrown 0.13.2", 3811 3810 ] 3812 - 3813 - [[package]] 3814 - name = "overload" 3815 - version = "0.1.1" 3816 - source = "registry+https://github.com/rust-lang/crates.io-index" 3817 - checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" 3818 3811 3819 3812 [[package]] 3820 3813 name = "p256" ··· 4500 4493 ] 4501 4494 4502 4495 [[package]] 4496 + name = "reflector" 4497 + version = "0.1.0" 4498 + dependencies = [ 4499 + "clap", 4500 + "log", 4501 + "poem", 4502 + "serde", 4503 + "tokio", 4504 + "tracing-subscriber", 4505 + ] 4506 + 4507 + [[package]] 4503 4508 name = "regex" 4504 4509 version = "1.11.1" 4505 4510 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 4507 4512 dependencies = [ 4508 4513 "aho-corasick", 4509 4514 "memchr", 4510 - "regex-automata 0.4.9", 4511 - "regex-syntax 0.8.5", 4512 - ] 4513 - 4514 - [[package]] 4515 - name = "regex-automata" 4516 - version = "0.1.10" 4517 - source = "registry+https://github.com/rust-lang/crates.io-index" 4518 - checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" 4519 - dependencies = [ 4520 - "regex-syntax 0.6.29", 4515 + "regex-automata", 4516 + "regex-syntax", 4521 4517 ] 4522 4518 4523 4519 [[package]] ··· 4528 4524 dependencies = [ 4529 4525 "aho-corasick", 4530 4526 "memchr", 4531 - "regex-syntax 0.8.5", 4527 + "regex-syntax", 4532 4528 ] 4533 - 4534 - [[package]] 4535 - name = "regex-syntax" 4536 - version = "0.6.29" 4537 - source = "registry+https://github.com/rust-lang/crates.io-index" 4538 - checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" 4539 4529 4540 4530 [[package]] 4541 4531 name = "regex-syntax" ··· 5650 5640 5651 5641 [[package]] 5652 5642 name = "tokio" 5653 - version = "1.47.0" 5643 + version = "1.47.1" 5654 5644 source = "registry+https://github.com/rust-lang/crates.io-index" 5655 - checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35" 5645 + checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" 5656 5646 dependencies = [ 5657 5647 "backtrace", 5658 5648 "bytes", ··· 5893 5883 5894 5884 [[package]] 5895 5885 name = "tracing-subscriber" 5896 - version = "0.3.19" 5886 + version = "0.3.20" 5897 5887 source = "registry+https://github.com/rust-lang/crates.io-index" 5898 - checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" 5888 + checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" 5899 5889 dependencies = [ 5900 5890 "matchers", 5901 5891 "nu-ansi-term", 5902 5892 "once_cell", 5903 - "regex", 5893 + "regex-automata", 5904 5894 "sharded-slab", 5905 5895 "smallvec", 5906 5896 "thread_local",
+1
Cargo.toml
··· 11 11 "slingshot", 12 12 "quasar", 13 13 "pocket", 14 + "reflector", 14 15 ]
+8 -1
Makefile
··· 5 5 cargo test --all-features 6 6 7 7 fmt: 8 - cargo fmt --package links --package constellation --package ufos --package spacedust --package who-am-i --package slingshot --package pocket 8 + cargo fmt --package links \ 9 + --package constellation \ 10 + --package ufos \ 11 + --package spacedust \ 12 + --package who-am-i \ 13 + --package slingshot \ 14 + --package pocket \ 15 + --package reflector 9 16 cargo +nightly fmt --package jetstream 10 17 11 18 clippy:
+12
reflector/Cargo.toml
··· 1 + [package] 2 + name = "reflector" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies] 7 + clap = { version = "4.5.47", features = ["derive"] } 8 + log = "0.4.28" 9 + poem = "3.1.12" 10 + serde = { version = "1.0.219", features = ["derive"] } 11 + tokio = "1.47.1" 12 + tracing-subscriber = { version = "0.3.20", features = ["env-filter"] }
+9
reflector/readme.md
··· 1 + # reflector 2 + 3 + a tiny did:web service server that maps subdomains to a single service endpoint 4 + 5 + receiving requests from multiple subdomains is left as a problem for the reverse proxy to solve, since acme wildcard certificates (ie. letsencrypt) require the most complicated and involved challenge type (DNS). 6 + 7 + caddy [has good support for](https://caddyserver.com/docs/caddyfile/patterns#wildcard-certificates) configuring the wildcard DNS challenge with various DNS providers, and also supports [on-demand](https://caddyserver.com/docs/automatic-https#using-on-demand-tls) provisioning via the simpler methods. 8 + 9 + if you only need a small fixed number of subdomains, you can also use certbot or otherwise individually configure them in your reverse proxy.
+83
reflector/src/main.rs
··· 1 + use clap::Parser; 2 + use poem::{ 3 + EndpointExt, Route, Server, get, handler, 4 + listener::TcpListener, 5 + middleware::{AddData, Tracing}, 6 + web::{Data, Json, TypedHeader, headers::Host}, 7 + }; 8 + use serde::Serialize; 9 + 10 + #[handler] 11 + fn hello() -> String { 12 + "ɹoʇɔǝʅⅎǝɹ".to_string() 13 + } 14 + 15 + #[derive(Debug, Serialize)] 16 + struct DidDoc { 17 + id: String, 18 + service: [DidService; 1], 19 + } 20 + 21 + #[derive(Debug, Clone, Serialize)] 22 + struct DidService { 23 + id: String, 24 + r#type: String, 25 + service_endpoint: String, 26 + } 27 + 28 + #[handler] 29 + fn did_doc(TypedHeader(host): TypedHeader<Host>, service: Data<&DidService>) -> Json<DidDoc> { 30 + Json(DidDoc { 31 + id: format!("did:web:{}", host.hostname()), 32 + service: [service.clone()], 33 + }) 34 + } 35 + 36 + /// Slingshot record edge cache 37 + #[derive(Parser, Debug, Clone)] 38 + #[command(version, about, long_about = None)] 39 + struct Args { 40 + /// The DID document service ID to serve 41 + /// 42 + /// must start with a '#', like `#bsky_appview' 43 + #[arg(long)] 44 + id: String, 45 + /// Service type 46 + /// 47 + /// Not sure exactly what its requirements are. 'BlueskyAppview' for example 48 + #[arg(long)] 49 + r#type: String, 50 + /// The HTTPS endpoint for the service 51 + #[arg(long)] 52 + service_endpoint: String, 53 + } 54 + 55 + impl From<Args> for DidService { 56 + fn from(a: Args) -> Self { 57 + Self { 58 + id: a.id, 59 + r#type: a.r#type, 60 + service_endpoint: a.service_endpoint, 61 + } 62 + } 63 + } 64 + 65 + #[tokio::main(flavor = "current_thread")] 66 + async fn main() { 67 + tracing_subscriber::fmt::init(); 68 + log::info!("ɹoʇɔǝʅⅎǝɹ"); 69 + 70 + let args = Args::parse(); 71 + let service: DidService = args.into(); 72 + 73 + Server::new(TcpListener::bind("0.0.0.0:3001")) 74 + .run( 75 + Route::new() 76 + .at("/", get(hello)) 77 + .at("/.well-known/did.json", get(did_doc)) 78 + .with(AddData::new(service)) 79 + .with(Tracing), 80 + ) 81 + .await 82 + .unwrap() 83 + }