crates/monetize-shop-pairing/src/sale_check/tests.rs
use super::*;
#[allow(unused_imports)]
use crate::test_fixtures::*;
use std::sync::Mutex;
const HOST: &str = "acme.test2.gunnar.rs";
const INVITE: &str = "0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0";
const BEARER: &str = "b7e1a0c9d8f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5c4b3a29180f7e6d5";
/// **A sold front's console, faked** as gunnar-ui-server answers: its login page, its status,
/// the first-login door (a challenge for an invite-shaped `?invite=`), and its repositories
/// (to the console's bearer only). The default serves `alice/welcome`.
#[derive(Clone)]
struct Console {
login: Option<(u16, String)>,
passkey_enabled: bool,
bootstrap_spent: bool,
door: (u16, String),
repos: Vec<&'static str>,
truncated: bool,
asked: Arc<Mutex<Vec<Asked>>>,
}
/// One request the console was asked: its path and query, and its bearer.
type Asked = (String, Option<String>);
impl Default for Console {
fn default() -> Self {
Console {
login: Some((200, format!("<html><title>Gunnar — log in</title><script>fetch('{}')</script></html>", console::LOGIN_PAGE_MARK))),
passkey_enabled: true,
bootstrap_spent: false,
door: (200, r#"{"publicKey":{"challenge":"c2FsZS1jaGVjaw","rp":{"name":"Gunnar"}},"ceremony":"x"}"#.into()),
repos: vec!["alice/welcome"],
truncated: false,
asked: Arc::default(),
}
}
}
impl Front for Console {
fn get(&self, path_and_query: &str, bearer: Option<&str>) -> Result<(u16, String), String> {
self.asked
.lock()
.unwrap()
.push((path_and_query.to_string(), bearer.map(str::to_string)));
let (path, q) = path_and_query
.split_once('?')
.unwrap_or((path_and_query, ""));
Ok(match path {
console::LOGIN_PATH => return self.login.clone().ok_or_else(|| "connection refused".to_string()),
console::AUTH_STATUS_PATH => (200, serde_json::json!({"passkey_enabled": self.passkey_enabled, "bootstrap_spent": self.bootstrap_spent}).to_string()),
console::REGISTER_START_PATH => {
let invite = q.split('&').find_map(|kv| kv.strip_prefix("invite=")).unwrap_or_default();
if (16..=128).contains(&invite.len()) {
self.door.clone()
} else {
(400, "that is not an invite this console can register a passkey with".into())
}
}
console::REPOS_PATH if bearer == Some(BEARER) => {
let items: Vec<_> = self
.repos
.iter()
.map(|p| {
let (ns, name) = p.split_once('/').unwrap();
serde_json::json!({"path": p, "namespace": ns, "name": name, "visibility": "private"})
})
.collect();
(200, serde_json::json!({"items": items, "total": items.len(), "truncated": self.truncated}).to_string())
}
console::REPOS_PATH => (401, "unauthorized".into()),
_ => (404, "not found".into()),
})
}
}
fn judged(console: &Console) -> Result<String, String> {
judge(console, HOST, "alice", BEARER, INVITE)
}
/// ★ **S4**: a front that serves its login page, its door and exactly `alice/welcome` is
/// proven — and the check asked each door as the buyer and the console do: the login page and
/// the door with no bearer, the door with the mail's own invite for the buyer's account, the
/// repositories with the console's bearer.
#[test]
fn a_front_that_serves_what_was_sold_is_proven_by_its_public_doors() {
let console = Console::default();
let proven = judged(&console).expect("a serving front is proven");
assert!(
proven.contains("alice/welcome") && proven.contains(HOST),
"{proven}"
);
let asked = console.asked.lock().unwrap().clone();
let paths: Vec<&str> = asked
.iter()
.map(|(p, _)| p.split('?').next().unwrap())
.collect();
assert_eq!(
paths,
[
console::LOGIN_PATH,
console::AUTH_STATUS_PATH,
console::REGISTER_START_PATH,
console::REPOS_PATH
]
);
assert!(
asked[..3].iter().all(|(_, b)| b.is_none()),
"the public doors are asked as the buyer: no bearer"
);
assert_eq!(
asked[2].0,
format!(
"{}?invite={INVITE}&user=alice",
console::REGISTER_START_PATH
),
"the mail's own link"
);
assert_eq!(
asked[3],
(
format!("{}?limit={}", console::REPOS_PATH, console::REPOS_MAX),
Some(BEARER.to_string())
)
);
}
/// ★ **S4**: no sale is proven by a front that only half serves — each case is refused and
/// says which door did not answer.
#[test]
fn a_front_missing_its_login_page_its_door_or_exactly_one_welcome_is_refused() {
let d = Console::default;
let cases: Vec<(&str, Console, &str)> = vec![
(
"login down",
Console { login: None, ..d() },
"the login page",
),
(
"login 502",
Console {
login: Some((502, "bad gateway".into())),
..d()
},
"HTTP 502",
),
(
"not the console",
Console {
login: Some((200, "<html>nginx welcome</html>".into())),
..d()
},
"does not hold /auth/passkey/login/start",
),
(
"no passkeys",
Console {
passkey_enabled: false,
..d()
},
"/passkey_enabled is false",
),
(
"door spent",
Console {
bootstrap_spent: true,
..d()
},
"spent",
),
(
"door 503",
Console {
door: (503, "gunnar is unavailable".into()),
..d()
},
"the first-login door",
),
(
"door no challenge",
Console {
door: (200, "{}".into()),
..d()
},
"no passkey challenge",
),
(
"no welcome",
Console {
repos: vec!["alice/other"],
..d()
},
"holds 0 items named \"welcome\"",
),
(
"two welcome",
Console {
repos: vec!["alice/welcome", "operator/welcome"],
..d()
},
"holds 2 items named \"welcome\"",
),
(
"another's welcome",
Console {
repos: vec!["bob/welcome"],
..d()
},
"not exactly alice/welcome",
),
(
"truncated",
Console {
truncated: true,
..d()
},
"/truncated is true",
),
];
for (case, console, says) in cases {
let why = judged(&console).expect_err(case);
assert!(why.contains(says), "{case}: {why}");
assert!(why.contains(HOST), "{case}: names the public front: {why}");
}
let why = judge(&Console::default(), HOST, "alice", "not-the-bearer", INVITE)
.expect_err("a bearer the console refuses");
assert!(why.contains("HTTP 401") && why.contains("welcome"), "{why}");
assert!(
judge(&Console::default(), HOST, " ", BEARER, INVITE).is_err(),
"no account sold, nothing to prove"
);
}
/// ★ The invite and the bearer are never in a word the check says, even from a front that
/// echoes what it was asked.
#[test]
fn the_check_never_says_the_invite_or_the_bearer() {
struct Echo;
impl Front for Echo {
fn get(&self, p: &str, b: Option<&str>) -> Result<(u16, String), String> {
if p.starts_with(console::LOGIN_PATH) || p.starts_with(console::AUTH_STATUS_PATH) {
return Console::default().get(p, b);
}
Ok((418, format!("you asked {p} with {b:?}")))
}
}
let why = judge(&Echo, HOST, "alice", BEARER, INVITE).unwrap_err();
assert!(!why.contains(INVITE) && !why.contains(BEARER), "{why}");
let why = judge(
&Console {
repos: vec![],
..Console::default()
},
HOST,
"alice",
BEARER,
INVITE,
)
.unwrap_err();
assert!(!why.contains(INVITE) && !why.contains(BEARER), "{why}");
}
#[test]
fn an_answer_is_read_whole_or_refused() {
assert_eq!(
parse_answer(b"HTTP/1.1 200 OK\r\ncontent-length: 5\r\n\r\nhello").unwrap(),
(200, "hello".into())
);
assert_eq!(parse_answer(b"HTTP/1.1 404 Not Found\r\nTransfer-Encoding: chunked\r\n\r\n3\r\nabc\r\n2;x=y\r\nde\r\n0\r\n\r\n").unwrap(), (404, "abcde".into()));
assert!(
parse_answer(b"HTTP/1.1 200 OK\r\ncontent-length: 9\r\n\r\nhello").is_err(),
"cut short"
);
assert!(
parse_answer(b"HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n5\r\nab").is_err(),
"cut short"
);
assert!(parse_answer(b"SSH-2.0-OpenSSH\r\n\r\n").is_err());
}
// ── over real HTTPS, in this process ───────────────────────────────────
/// **The console behind TLS** for `HOST` with `cert`/`key`, on a loopback port; each request
/// (its path and bearer, from its own head) answered by `console`.
fn serve(console: Console, cert: &str, key: &str) -> SocketAddr {
use rustls::pki_types::pem::PemObject as _;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
let certs = CertificateDer::pem_slice_iter(cert.as_bytes())
.collect::<Result<Vec<_>, _>>()
.unwrap();
let key = PrivateKeyDer::from_pem_slice(key.as_bytes()).unwrap();
let cfg = Arc::new(
rustls::ServerConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_single_cert(certs, key)
.unwrap(),
);
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
std::thread::spawn(move || {
for tcp in listener.incoming().flatten() {
let (cfg, console) = (Arc::clone(&cfg), console.clone());
std::thread::spawn(move || {
let mut tls =
rustls::StreamOwned::new(rustls::ServerConnection::new(cfg).unwrap(), tcp);
let mut head = Vec::new();
let mut b = [0u8; 1];
while !head.ends_with(b"\r\n\r\n") {
match tls.read(&mut b) {
Ok(1) => head.push(b[0]),
_ => return,
}
}
let head = String::from_utf8_lossy(&head).to_string();
let path = head
.split_whitespace()
.nth(1)
.unwrap_or_default()
.to_string();
let host_ok = head
.lines()
.any(|l| l.eq_ignore_ascii_case(&format!("host: {HOST}")));
let bearer = head
.lines()
.find_map(|l| l.strip_prefix("Authorization: Bearer "))
.map(|s| s.trim().to_string());
let (status, body) = if host_ok {
console
.get(&path, bearer.as_deref())
.unwrap_or((502, String::new()))
} else {
(421, "misdirected".into())
};
let _ = write!(tls, "HTTP/1.1 {status} X\r\ncontent-type: text/plain\r\ncontent-length: {}\r\nconnection: close\r\n\r\n{body}", body.len());
tls.conn.send_close_notify();
let _ = tls.flush();
});
}
});
addr
}
/// ★ **S4, the real client**: the shop reaches the sold front over HTTPS, trusting the
/// certificate it minted for that front (kept at the install, [`keep_front_cert`]) — and
/// proves the sale; a front whose welcome repository is missing is refused over the wire too.
#[test]
fn the_shop_proves_the_sale_over_https_trusting_the_certificate_it_minted() {
let (cert, key) = crate::self_signed(&[HOST.to_string()]).unwrap();
let run = tempfile::tempdir().unwrap();
let feed = std::collections::BTreeMap::from([
(format!("tls.{HOST}.cert"), cert.clone()),
(format!("tls.{HOST}.key"), key.clone()),
]);
keep_front_cert(run.path(), HOST, &feed).unwrap();
assert_eq!(
std::fs::read_to_string(run.path().join(FRONT_CERT)).unwrap(),
cert,
"the certificate alone is kept"
);
assert!(!std::fs::read_to_string(run.path().join(FRONT_CERT))
.unwrap()
.contains("PRIVATE KEY"));
let serving = serve(Console::default(), &cert, &key);
let facts = monetize_server::testing::lifecycles::gunnar_facts();
let at = SaleCheckAt {
facts: &facts,
company: "acme",
host: HOST,
account: "alice",
front: None,
run_dir: run.path(),
console_token: BEARER,
first_login: INVITE,
};
let proven = check_reaching(&at, &|_| Ok(serving)).expect("the sale is proven over HTTPS");
assert!(proven.contains("alice/welcome"), "{proven}");
let no_welcome = serve(
Console {
repos: vec![],
..Console::default()
},
&cert,
&key,
);
let why = check_reaching(&at, &|_| Ok(no_welcome)).expect_err("no welcome repository, no sale");
assert!(why.contains("holds 0 items"), "{why}");
}
/// **The console behind TLS at its canonical www name** (WWW-CANON, edda estate-front 0.3.3): a request
/// to the bare `HOST` is a 301 (GET/HEAD) or a 308 (any other method) to `https://www.HOST` with the same
/// path; the console answers at `www.HOST` alone. Every head is kept in `seen`.
fn serve_www(console: Console, cert: &str, key: &str, seen: Arc<Mutex<Vec<String>>>) -> SocketAddr {
use rustls::pki_types::pem::PemObject as _;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
let certs = CertificateDer::pem_slice_iter(cert.as_bytes())
.collect::<Result<Vec<_>, _>>()
.unwrap();
let key = PrivateKeyDer::from_pem_slice(key.as_bytes()).unwrap();
let cfg = Arc::new(
rustls::ServerConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_single_cert(certs, key)
.unwrap(),
);
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
std::thread::spawn(move || {
for tcp in listener.incoming().flatten() {
let (cfg, console, seen) = (Arc::clone(&cfg), console.clone(), Arc::clone(&seen));
std::thread::spawn(move || {
let mut tls =
rustls::StreamOwned::new(rustls::ServerConnection::new(cfg).unwrap(), tcp);
let mut head = Vec::new();
let mut b = [0u8; 1];
while !head.ends_with(b"\r\n\r\n") {
match tls.read(&mut b) {
Ok(1) => head.push(b[0]),
_ => return,
}
}
let head = String::from_utf8_lossy(&head).to_string();
seen.lock().unwrap().push(head.clone());
let method = head
.split_whitespace()
.next()
.unwrap_or_default()
.to_string();
let path = head
.split_whitespace()
.nth(1)
.unwrap_or_default()
.to_string();
let www = head
.lines()
.any(|l| l.eq_ignore_ascii_case(&format!("host: www.{HOST}")));
let bare = head
.lines()
.any(|l| l.eq_ignore_ascii_case(&format!("host: {HOST}")));
let bearer = head
.lines()
.find_map(|l| l.strip_prefix("Authorization: Bearer "))
.map(|s| s.trim().to_string());
let answer = if bare {
let code = if matches!(method.as_str(), "GET" | "HEAD") {
301
} else {
308
};
format!("HTTP/1.1 {code} X\r\nlocation: https://www.{HOST}{path}\r\ncontent-length: 0\r\nconnection: close\r\n\r\n")
} else {
let (status, body) = if www {
console
.get(&path, bearer.as_deref())
.unwrap_or((502, String::new()))
} else {
(421, "misdirected".into())
};
format!("HTTP/1.1 {status} X\r\ncontent-type: text/plain\r\ncontent-length: {}\r\nconnection: close\r\n\r\n{body}", body.len())
};
let _ = tls.write_all(answer.as_bytes());
tls.conn.send_close_notify();
let _ = tls.flush();
});
}
});
addr
}
/// ★ **WWW-CANON: the sale check follows the bare host's one hop to its www name** (HOL-PRODUCTS'
/// gate 2026-10-31: test3.holger.rs stayed "installing (paired)" for 90 min, its sale check got
/// the front's 301). A 301/308 from `https://<host>` to `https://www.<host>` with the same path is
/// followed once, under the www name; any other redirect is the answer, as before.
#[test]
fn the_sale_check_follows_the_bare_hosts_one_hop_to_www() {
let (cert, key) = crate::self_signed(&[HOST.to_string(), format!("www.{HOST}")]).unwrap();
let seen = Arc::new(Mutex::new(Vec::new()));
let addr = serve_www(Console::default(), &cert, &key, Arc::clone(&seen));
let front = Https::new(HOST, addr, Some(cert.as_bytes())).unwrap();
let proven = judge(&front, HOST, "alice", BEARER, INVITE).expect("the sale is proven at www");
assert!(proven.contains("alice/welcome"), "{proven}");
let heads = seen.lock().unwrap().clone();
assert!(
heads
.iter()
.any(|h| h.contains(&format!("Host: www.{HOST}\r\n"))),
"asked at www: {heads:?}"
);
// A POST keeps its method and body through the 308.
assert_eq!(front.post("/x", "{}", None).unwrap().0, 404);
assert!(
seen.lock()
.unwrap()
.iter()
.any(|h| h.starts_with("POST /x HTTP/1.1")
&& h.contains(&format!("Host: www.{HOST}\r\n")))
);
// A redirect anywhere else is the answer itself.
assert!(super::www_hop(
HOST,
"/a",
301,
Some(&format!("https://www.{HOST}/a"))
));
assert!(!super::www_hop(
HOST,
"/a",
302,
Some(&format!("https://www.{HOST}/a"))
));
assert!(!super::www_hop(
HOST,
"/a",
301,
Some("https://evil.example/a")
));
assert!(!super::www_hop(
HOST,
"/a",
301,
Some(&format!("https://www.{HOST}/b"))
));
assert!(!super::www_hop(
&format!("www.{HOST}"),
"/a",
301,
Some(&format!("https://www.www.{HOST}/a"))
));
}
/// ★ A front the shop did not mint for and no root vouches for is not believed; nor is an
/// address that does not answer.
#[test]
fn a_front_with_a_certificate_nobody_vouches_for_is_not_believed() {
let (cert, key) = crate::self_signed(&[HOST.to_string()]).unwrap();
let (other, _) = crate::self_signed(&[HOST.to_string()]).unwrap();
let addr = serve(Console::default(), &cert, &key);
let unpinned = Https::new(HOST, addr, None).unwrap();
let why = judge(&unpinned, HOST, "alice", BEARER, INVITE).expect_err("no root, no pin");
assert!(
why.contains("the login page") && why.to_lowercase().contains("certificate"),
"{why}"
);
let wrong = Https::new(HOST, addr, Some(other.as_bytes())).unwrap();
assert!(
judge(&wrong, HOST, "alice", BEARER, INVITE).is_err(),
"another certificate pinned"
);
let shut = std::net::TcpListener::bind("127.0.0.1:0")
.unwrap()
.local_addr()
.unwrap();
let nobody = Https::new(HOST, shut, Some(cert.as_bytes())).unwrap();
assert!(
judge(&nobody, HOST, "alice", BEARER, INVITE).is_err(),
"nobody answers"
);
// No certificate minted for the front: none kept, an old one taken away.
let run = tempfile::tempdir().unwrap();
std::fs::write(run.path().join(FRONT_CERT), &cert).unwrap();
keep_front_cert(run.path(), HOST, &Default::default()).unwrap();
assert!(!run.path().join(FRONT_CERT).exists());
}
/// ★ **S4: the shop's installer proves the sale itself** — `ShopPairing` answers the shop's
/// sale check (the seam's default proves nothing and captures nothing), here at an address
/// nothing listens on: refused, and it says the public front.
#[test]
fn the_shops_pairing_answers_the_sale_check_from_the_public_front() {
use monetize_server::estate_order::Installer as _;
let run = tempfile::tempdir().unwrap();
let shop = crate::ShopPairing {
sale_feed: Default::default(),
budget_s: 600,
fleet_late_s: 0,
installer_link_psk: true,
};
let facts = monetize_server::testing::lifecycles::gunnar_facts();
let at = SaleCheckAt {
facts: &facts,
company: "acme",
host: "acme.invalid",
account: "alice",
front: None,
run_dir: run.path(),
console_token: BEARER,
first_login: INVITE,
};
let why = shop
.sale_check(&at)
.expect_err("nothing serves acme.invalid");
assert!(
why.contains("acme.invalid") && !why.contains("proves no sale check"),
"{why}"
);
}
/// ★ **The first-admin door** (owner 2026-10-22, `site first-link`): open to the custody's
/// invite, spent once the first admin signed in, closed when the invite no longer opens it.
#[test]
fn the_first_admin_door_is_open_spent_or_closed() {
use monetize_server::estate_order::FirstDoor;
assert_eq!(
first_door_for(&gunnar(), &Console::default(), HOST, "alice", INVITE),
Ok(FirstDoor::Open)
);
let spent = Console {
bootstrap_spent: true,
..Console::default()
};
assert_eq!(
first_door_for(&gunnar(), &spent, HOST, "alice", INVITE),
Ok(FirstDoor::Spent)
);
let closed = Console {
door: (401, "this invite has expired".into()),
..Console::default()
};
match first_door_for(&gunnar(), &closed, HOST, "alice", INVITE) {
Ok(FirstDoor::Closed(why)) => {
assert!(why.contains("HTTP 401") && !why.contains(INVITE), "{why}")
}
other => panic!("{other:?}"),
}
let down = Console {
passkey_enabled: false,
..Console::default()
};
assert!(matches!(
first_door_for(&gunnar(), &down, HOST, "alice", INVITE),
Ok(FirstDoor::Closed(_))
));
}
/// **A front that takes the request and then drips its answer**, one byte every 100 ms,
/// for as long as anyone reads: every read is answered within [`PATIENCE`], the answer
/// never ends.
fn dripping(cert: &str, key: &str) -> SocketAddr {
use rustls::pki_types::pem::PemObject as _;
use rustls::pki_types::{CertificateDer, PrivateKeyDer};
let certs = CertificateDer::pem_slice_iter(cert.as_bytes())
.collect::<Result<Vec<_>, _>>()
.unwrap();
let key = PrivateKeyDer::from_pem_slice(key.as_bytes()).unwrap();
let cfg = Arc::new(
rustls::ServerConfig::builder_with_provider(Arc::new(
rustls::crypto::ring::default_provider(),
))
.with_safe_default_protocol_versions()
.unwrap()
.with_no_client_auth()
.with_single_cert(certs, key)
.unwrap(),
);
let listener = std::net::TcpListener::bind("127.0.0.1:0").unwrap();
let addr = listener.local_addr().unwrap();
std::thread::spawn(move || {
for tcp in listener.incoming().flatten() {
let cfg = Arc::clone(&cfg);
std::thread::spawn(move || {
let mut tls =
rustls::StreamOwned::new(rustls::ServerConnection::new(cfg).unwrap(), tcp);
let mut head = Vec::new();
let mut b = [0u8; 1];
while !head.ends_with(b"\r\n\r\n") {
match tls.read(&mut b) {
Ok(1) => head.push(b[0]),
_ => return,
}
}
if write!(
tls,
"HTTP/1.1 200 X\r\ncontent-type: text/plain\r\ncontent-length: 1000000\r\n\r\n"
)
.and_then(|()| tls.flush())
.is_err()
{
return;
}
while tls.write_all(b"a").and_then(|()| tls.flush()).is_ok() {
std::thread::sleep(std::time::Duration::from_millis(100));
}
});
}
});
addr
}
/// ★ A22 #6 (F-T-09): **a front that drips its answer cannot hold the sale check**: each
/// request has a total deadline, not only a deadline per read, and the check says so.
#[test]
fn a_front_that_drips_its_answer_is_refused_within_the_deadline() {
let (cert, key) = crate::self_signed(&[HOST.to_string()]).unwrap();
let addr = dripping(&cert, &key);
let mut front = Https::new(HOST, addr, Some(cert.as_bytes())).unwrap();
assert_eq!(front.within, ANSWER_WITHIN);
front.within = std::time::Duration::from_secs(1);
let started = std::time::Instant::now();
let (tx, rx) = std::sync::mpsc::channel();
std::thread::spawn(move || {
let _ = tx.send(front.get("/login", None));
});
let got = rx
.recv_timeout(std::time::Duration::from_secs(45))
.expect("the request ends within its deadline, not when the front stops dripping");
let why = got.expect_err("a dripped answer is no answer");
assert!(
why.contains("did not answer GET /login within 1 s"),
"{why}"
);
assert!(
started.elapsed() < std::time::Duration::from_secs(5),
"{:?}",
started.elapsed()
);
}
/// The exchange's deadline grows with the body it sends: 32 MiB at a 256 KiB/s floor.
#[test]
fn a_large_body_has_the_time_to_be_sent() {
let w = std::time::Duration::from_secs(30);
assert_eq!(within_for(w, 0), w);
assert_eq!(within_for(w, 100), w);
assert_eq!(
within_for(w, 32 << 20),
w + std::time::Duration::from_secs(128)
);
}