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

acme????

Changed files
+222 -11
slingshot
+189
Cargo.lock
···
]
[[package]]
+
name = "asn1-rs"
+
version = "0.7.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "56624a96882bb8c26d61312ae18cb45868e5a9992ea73c58e45c3101e56a1e60"
+
dependencies = [
+
"asn1-rs-derive",
+
"asn1-rs-impl",
+
"displaydoc",
+
"nom",
+
"num-traits",
+
"rusticata-macros",
+
"thiserror 2.0.12",
+
"time",
+
]
+
+
[[package]]
+
name = "asn1-rs-derive"
+
version = "0.6.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn 2.0.103",
+
"synstructure",
+
]
+
+
[[package]]
+
name = "asn1-rs-impl"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7"
+
dependencies = [
+
"proc-macro2",
+
"quote",
+
"syn 2.0.103",
+
]
+
+
[[package]]
name = "async-channel"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
+
name = "der-parser"
+
version = "10.0.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6"
+
dependencies = [
+
"asn1-rs",
+
"displaydoc",
+
"nom",
+
"num-bigint",
+
"num-traits",
+
"rusticata-macros",
+
]
+
+
[[package]]
name = "deranged"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4"
dependencies = [
"cfg-if",
+
"js-sys",
"libc",
"r-efi",
"wasi 0.14.2+wasi-0.2.4",
+
"wasm-bindgen",
[[package]]
···
[[package]]
+
name = "lru-slab"
+
version = "0.1.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
+
+
[[package]]
name = "lsm-tree"
version = "2.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
+
name = "oid-registry"
+
version = "0.8.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7"
+
dependencies = [
+
"asn1-rs",
+
]
+
+
[[package]]
name = "once_cell"
version = "1.21.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f977080932c87287147dca052951c3e2696f8759863f6b4e4c0c9ffe7a4cc8b"
dependencies = [
+
"base64 0.22.1",
"bytes",
+
"chrono",
"futures-util",
"headers",
"http",
···
"pin-project-lite",
"poem-derive",
"quick-xml",
+
"rcgen",
"regex",
+
"reqwest",
"rfc7239",
+
"ring",
+
"rustls-pemfile",
"serde",
"serde_json",
"serde_urlencoded",
···
"tempfile",
"thiserror 2.0.12",
"tokio",
+
"tokio-rustls 0.26.2",
"tokio-stream",
"tokio-util",
"tracing",
"wildmatch",
+
"x509-parser",
[[package]]
···
[[package]]
+
name = "quinn"
+
version = "0.11.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8"
+
dependencies = [
+
"bytes",
+
"cfg_aliases",
+
"pin-project-lite",
+
"quinn-proto",
+
"quinn-udp",
+
"rustc-hash 2.1.1",
+
"rustls 0.23.28",
+
"socket2 0.5.9",
+
"thiserror 2.0.12",
+
"tokio",
+
"tracing",
+
"web-time",
+
]
+
+
[[package]]
+
name = "quinn-proto"
+
version = "0.11.12"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e"
+
dependencies = [
+
"bytes",
+
"getrandom 0.3.3",
+
"lru-slab",
+
"rand 0.9.1",
+
"ring",
+
"rustc-hash 2.1.1",
+
"rustls 0.23.28",
+
"rustls-pki-types",
+
"slab",
+
"thiserror 2.0.12",
+
"tinyvec",
+
"tracing",
+
"web-time",
+
]
+
+
[[package]]
+
name = "quinn-udp"
+
version = "0.5.13"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "fcebb1209ee276352ef14ff8732e24cc2b02bbac986cd74a4c81bcb2f9881970"
+
dependencies = [
+
"cfg_aliases",
+
"libc",
+
"once_cell",
+
"socket2 0.5.9",
+
"tracing",
+
"windows-sys 0.52.0",
+
]
+
+
[[package]]
name = "quote"
version = "1.0.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
[[package]]
+
name = "rcgen"
+
version = "0.12.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "48406db8ac1f3cbc7dcdb56ec355343817958a356ff430259bb07baf7607e1e1"
+
dependencies = [
+
"pem",
+
"ring",
+
"time",
+
"yasna",
+
]
+
+
[[package]]
name = "redox_syscall"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"native-tls",
"percent-encoding",
"pin-project-lite",
+
"quinn",
+
"rustls 0.23.28",
+
"rustls-native-certs",
"rustls-pki-types",
"serde",
"serde_json",
···
"sync_wrapper",
"tokio",
"tokio-native-tls",
+
"tokio-rustls 0.26.2",
"tokio-util",
"tower",
"tower-http",
···
[[package]]
+
name = "rusticata-macros"
+
version = "4.1.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632"
+
dependencies = [
+
"nom",
+
]
+
+
[[package]]
name = "rustix"
version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643"
dependencies = [
"aws-lc-rs",
+
"log",
"once_cell",
+
"ring",
"rustls-pki-types",
"rustls-webpki 0.103.3",
"subtle",
···
version = "1.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
+
dependencies = [
+
"web-time",
+
]
[[package]]
name = "rustls-webpki"
···
[[package]]
+
name = "x509-parser"
+
version = "0.17.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4569f339c0c402346d4a75a9e39cf8dad310e287eef1ff56d4c68e5067f53460"
+
dependencies = [
+
"asn1-rs",
+
"data-encoding",
+
"der-parser",
+
"lazy_static",
+
"nom",
+
"oid-registry",
+
"rusticata-macros",
+
"thiserror 2.0.12",
+
"time",
+
]
+
+
[[package]]
name = "xxhash-rust"
version = "0.8.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
+
+
[[package]]
+
name = "yasna"
+
version = "0.5.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd"
+
dependencies = [
+
"time",
+
]
[[package]]
name = "yoke"
+1 -1
slingshot/Cargo.toml
···
log = "0.4.27"
metrics = "0.24.2"
metrics-exporter-prometheus = { version = "0.17.1", features = ["http-listener"] }
-
poem = "3.1.12"
+
poem = { version = "3.1.12", features = ["acme"] }
poem-openapi = { version = "5.1.16", features = ["scalar"] }
reqwest = { version = "0.12.22", features = ["json"] }
serde = { version = "1.0.219", features = ["derive"] }
+3 -1
slingshot/src/error.rs
···
#[derive(Debug, Error)]
pub enum ServerError {
+
#[error("server build error: {0}")]
+
AcmeBuildError(std::io::Error),
#[error("server exited: {0}")]
-
ServerExited(String),
+
ServerExited(std::io::Error),
}
#[derive(Debug, Error)]
+29 -9
slingshot/src/server.rs
···
use std::sync::Arc;
use tokio_util::sync::CancellationToken;
-
use poem::{Endpoint, Route, Server, endpoint::make_sync, listener::TcpListener};
+
use poem::{
+
Endpoint, Route, Server,
+
endpoint::make_sync,
+
listener::{
+
Listener, TcpListener,
+
acme::{AutoCert, LETS_ENCRYPT_PRODUCTION},
+
},
+
};
use poem_openapi::{
ApiResponse, Object, OpenApi, OpenApiService, param::Query, payload::Json, types::Example,
};
···
///
/// - PDS proxying offers a level of client IP anonymity from slingshot
/// - slingshot *may* implement more generous per-user rate-limits for proxied requests in the future
-
fn get_did_doc(host: String) -> impl Endpoint {
+
fn get_did_doc(host: &str) -> impl Endpoint + use<> {
let doc = poem::web::Json(AppViewDoc {
id: format!("did:web:{host}"),
service: [AppViewService {
···
.server("http://localhost:3000")
.url_prefix("/xrpc");
-
let mut app = Route::new()
+
let app = Route::new()
.nest("/", api_service.scalar())
.nest("/openapi.json", api_service.spec_endpoint())
.nest("/xrpc/", api_service);
if let Some(host) = host {
-
app = app.at("/.well-known/did.json", get_did_doc(host));
-
};
+
let app = app.at("/.well-known/did.json", get_did_doc(&host));
+
+
let auto_cert = AutoCert::builder()
+
.directory_url(LETS_ENCRYPT_PRODUCTION)
+
.domain(&host)
+
.build()
+
.map_err(ServerError::AcmeBuildError)?;
-
Server::new(TcpListener::bind("127.0.0.1:3000"))
-
.run(app)
-
.await
-
.map_err(|e| ServerError::ServerExited(format!("uh oh: {e:?}")))
+
Server::new(TcpListener::bind("0.0.0.0:443").acme(auto_cert))
+
.name("slingshot")
+
.run(app)
+
.await
+
.map_err(ServerError::ServerExited)
+
} else {
+
Server::new(TcpListener::bind("127.0.0.1:3000"))
+
.name("slingshot")
+
.run(app)
+
.await
+
.map_err(ServerError::ServerExited)
+
}
}