Now let's take a silly one
0

Configure Feed

Select the types of activity you want to include in your feed.

#tangled_knot atproto & health endpoint

Lewis: May this revision serve well! <lu5a@proton.me>

author
Lewis
date (Jun 22, 2026, 10:29 PM +0300) commit ab11b917 parent 28b11191 change-id qylvpqvk
+86 -14
+19 -12
crates/knot-atproto/src/identity.rs
··· 8 8 use sha2::{Digest, Sha256}; 9 9 10 10 const PLC_OP_TYPE: &str = "plc_operation"; 11 - const ATPROTO_PDS_SERVICE: &str = "atproto_pds"; 12 - const PDS_SERVICE_TYPE: &str = "AtprotoPersonalDataServer"; 13 11 const ATPROTO_METHOD: &str = "atproto"; 14 12 const KNOT_HOME_SERVICE: &str = "tangled_knot"; 15 13 const KNOT_HOME_TYPE: &str = "TangledKnot"; ··· 170 168 "publicKeyMultibase": multikey_secp256k1(signing_key) 171 169 }], 172 170 "service": [{ 173 - "id": format!("#{ATPROTO_PDS_SERVICE}"), 174 - "type": PDS_SERVICE_TYPE, 171 + "id": format!("#{KNOT_HOME_SERVICE}"), 172 + "type": KNOT_HOME_TYPE, 175 173 "serviceEndpoint": service_url 176 174 }] 177 175 }) ··· 308 306 } 309 307 310 308 #[test] 311 - fn the_knot_document_publishes_the_signing_key_and_resolves_round_trip() { 309 + fn the_knot_document_declares_its_signing_key_and_tangled_knot_service() { 312 310 let key = signer(7); 313 311 let knot = KnotId::new("did:web:knot.oyster.cafe").unwrap(); 314 312 let document = knot_did_document(&knot, &key.public_key(), "https://knot.oyster.cafe"); 315 - let body = serde_json::to_vec(&document).unwrap(); 316 313 317 - let account = knot_types::AccountDid::new(knot.as_str()).unwrap(); 318 - let identity = crate::resolve::identity_from_document(&account, &body).unwrap(); 319 314 assert_eq!( 320 - identity.signing_key.bytes.as_ref(), 321 - key.public_key().as_bytes(), 322 - "published verification method is knot's own signing key" 315 + document["verificationMethod"][0]["id"], "did:web:knot.oyster.cafe#atproto", 316 + "knot publishes its signing key under the atproto method" 323 317 ); 324 - assert_eq!(identity.pds.as_str(), "https://knot.oyster.cafe/"); 318 + assert_eq!( 319 + document["verificationMethod"][0]["publicKeyMultibase"], 320 + serde_json::Value::String(multikey_secp256k1(&key.public_key())), 321 + "published verification method is the knot's own signing key" 322 + ); 323 + assert_eq!( 324 + document["service"][0], 325 + serde_json::json!({ 326 + "id": "#tangled_knot", 327 + "type": "TangledKnot", 328 + "serviceEndpoint": "https://knot.oyster.cafe" 329 + }), 330 + "knot self-declares its tangled_knot service at the knot root" 331 + ); 325 332 } 326 333 }
+1 -2
crates/knot-ssh/src/roster.rs
··· 243 243 ) 244 244 } 245 245 246 - type Responder = 247 - Box<dyn Fn(&HttpRequest) -> Result<HttpResponse, NetworkError> + Send + Sync>; 246 + type Responder = Box<dyn Fn(&HttpRequest) -> Result<HttpResponse, NetworkError> + Send + Sync>; 248 247 249 248 struct Harness { 250 249 index: Arc<Index>,
+1
crates/knot-xrpc/src/lib.rs
··· 201 201 Arc::clone(&state), 202 202 enforce_pre_auth_limit::<H, C>, 203 203 )) 204 + .route(service::HEALTH_ROUTE, get(service::health)) 204 205 .route(events::EVENTS_ROUTE, get(events::events::<H, C>)) 205 206 .with_state(state) 206 207 }
+13
crates/knot-xrpc/src/service.rs
··· 12 12 13 13 pub(crate) const VERSION_ROUTE: &str = "/xrpc/sh.tangled.knot.version"; 14 14 pub(crate) const OWNER_ROUTE: &str = "/xrpc/sh.tangled.owner"; 15 + pub(crate) const HEALTH_ROUTE: &str = "/xrpc/_health"; 15 16 16 17 const GO_PARITY_VERSION: &str = "v1.15.0"; 17 18 ··· 19 20 struct VersionWire { 20 21 version: String, 21 22 capabilities: [&'static str; 1], 23 + } 24 + 25 + #[derive(Serialize)] 26 + struct HealthWire { 27 + version: String, 28 + } 29 + 30 + pub(crate) async fn health() -> Response { 31 + Json(HealthWire { 32 + version: format!("knot2 {}", env!("CARGO_PKG_VERSION")), 33 + }) 34 + .into_response() 22 35 } 23 36 24 37 #[derive(Serialize)]
+52
crates/knot-xrpc/src/tests.rs
··· 2111 2111 } 2112 2112 2113 2113 #[tokio::test] 2114 + async fn health_is_unauthenticated_and_exempt_from_shedding() { 2115 + use axum::body::Body; 2116 + use axum::extract::ConnectInfo; 2117 + use std::net::SocketAddr; 2118 + use tower::ServiceExt; 2119 + 2120 + let world = World::new(); 2121 + let app = crate::router(Arc::clone(&world.state)); 2122 + let peer = SocketAddr::from(([203, 0, 113, 9], 5555)); 2123 + 2124 + let statuses = futures::future::join_all((0..30).map(|_| { 2125 + let app = app.clone(); 2126 + async move { 2127 + let mut request = http::Request::builder() 2128 + .method("GET") 2129 + .uri(crate::service::HEALTH_ROUTE) 2130 + .body(Body::empty()) 2131 + .unwrap(); 2132 + request.extensions_mut().insert(ConnectInfo(peer)); 2133 + app.oneshot(request).await.unwrap() 2134 + } 2135 + })) 2136 + .await; 2137 + 2138 + assert!( 2139 + statuses 2140 + .iter() 2141 + .all(|response| response.status() == StatusCode::OK), 2142 + "health stays 200 even past the pre-auth burst, got {:?}", 2143 + statuses.iter().map(|r| r.status()).collect::<Vec<_>>() 2144 + ); 2145 + 2146 + let mut request = http::Request::builder() 2147 + .method("GET") 2148 + .uri(crate::service::HEALTH_ROUTE) 2149 + .body(Body::empty()) 2150 + .unwrap(); 2151 + request.extensions_mut().insert(ConnectInfo(peer)); 2152 + let response = app.oneshot(request).await.unwrap(); 2153 + let body = axum::body::to_bytes(response.into_body(), usize::MAX) 2154 + .await 2155 + .unwrap(); 2156 + let wire: serde_json::Value = serde_json::from_slice(&body).unwrap(); 2157 + assert!( 2158 + wire["version"] 2159 + .as_str() 2160 + .is_some_and(|v| v.starts_with("knot2 ")), 2161 + "health reports a knot2 version, got {wire}" 2162 + ); 2163 + } 2164 + 2165 + #[tokio::test] 2114 2166 async fn create_requires_a_reserved_key_for_a_did_web() { 2115 2167 let world = World::new(); 2116 2168 add_member_helper(&world).await;