crates/monetize-server/src/estate_order/tests/refeed.rs
//! **The ONE box feeds an already-laid estate its keys again** (MAIL-RELAY + NIGHT-PUBREPO,
//! 2026-10-28). See [`crate::estate_order::refeed`].
use super::*;
use crate::estate_order::refeed;
use crate::services::estate_order::EstateOrderService;
use monetize_proto as pb;
use monetize_proto::estate_order_server::EstateOrder as _;
/// The relay this box holds for the mains it lays (a value made for the test, never a real one).
const URL: &str = "smtps://estates%40mock.invalid:t0kenVALUEnever-shown@relay.mock.invalid:465";
const FROM: &str = "Estates <estates@mock.invalid>";
const TOKEN: &str = "t0kenVALUEnever-shown";
/// A laid, ready operator site `gunnar-rs` (run `gunnarrs`), handed off, laid while this box
/// held NO relay for its mains; `relay` names what the box holds now (`None`: nothing).
fn laid_site(name: &str, relay: Option<(&str, &str)>) -> SiteRig {
laid_site_of(name, GUNNAR, relay)
}
/// A site of the shop's: its label, its product, its host.
type Site = (&'static str, &'static str, &'static str);
/// gunnar.rs: a Gunnar site (its boxes take the mail relay's keys again, nothing else).
const GUNNAR: Site = ("gunnar-rs", "gunnar", "gunnar.rs");
/// holger.rs: a Holger site (its boxes take its public repositories too).
const HOLGER: Site = ("holger-rs", "holger", "holger.rs");
fn site_of(s: Site, public: &[&str]) -> crate::config::EstateConfig {
crate::config::EstateConfig {
product: s.1.into(),
vendor: "holdpay".into(),
site: s.2.into(),
owner: "ignalina".into(),
operator_site: true,
public_repositories: public.iter().map(|p| p.to_string()).collect(),
..Default::default()
}
}
/// [`laid_site`] for the site `s`.
fn laid_site_of(name: &str, s: Site, relay: Option<(&str, &str)>) -> SiteRig {
laid_declared(name, s, &[], relay)
}
/// [`laid_site_of`], `s` declared with `public` as its public repositories BEFORE its lay.
fn laid_declared(name: &str, s: Site, public: &[&str], relay: Option<(&str, &str)>) -> SiteRig {
let (label, product, _) = s;
let mut rig = if s == GUNNAR && public.is_empty() {
site_rig_with(name, false)
} else {
site_rig_with_sites(name, false, cfg(), vec![(label, site_of(s, public))])
};
let company = site::company_of(label);
let secrets = rig.4.join("secrets");
std::fs::create_dir_all(&secrets).unwrap();
Arc::get_mut(&mut rig.0)
.expect("the rig's state is not shared yet")
.estates
.relay_fed = Some(secrets.clone());
let (state, pay, kit) = (&rig.0, &rig.1, &rig.3);
kit.bundles.store(true, Ordering::SeqCst);
let run = site::start_site(
state,
label,
"first-admin@mock.invalid",
&EstateSizes::default(),
)
.unwrap();
pay.authorize(&run.handle.clone().unwrap().id);
drive(state, &company);
assert_eq!(
state.estates.get(&company).unwrap().phase,
phase::CAPTURED,
"{:#?}",
state.estates.get(&company).unwrap().history
);
state
.estates
.custody
.as_ref()
.unwrap()
.forget(&company)
.unwrap();
if let Some((url, from)) = relay {
// The box's relay of the site's OWN product (OX-RELAY2: one per product).
let (url_n, from_n, _) = sold_relay_names(product);
if !url.is_empty() {
monetize_product_wasm::secrets::write(&secrets, &url_n, url.as_bytes()).unwrap();
}
if !from.is_empty() {
monetize_product_wasm::secrets::write(&secrets, &from_n, from.as_bytes()).unwrap();
}
}
rig
}
fn relay_orders(state: &AppState, fleet: &str) -> Vec<monetize_embed::fleet::SignedOrder> {
orders_for(state, fleet, "main")
}
fn orders_for(
state: &AppState,
fleet: &str,
role: &str,
) -> Vec<monetize_embed::fleet::SignedOrder> {
let g = state.fleet.guardian().unwrap();
g.store
.orders_for(fleet, role, 0)
.into_iter()
.filter(|o| o.kind == monetize_embed::fleet::kind::REFEED)
.collect()
}
fn body_of(o: &monetize_embed::fleet::SignedOrder) -> BTreeMap<String, String> {
serde_json::from_str::<monetize_embed::fleet::Refeed>(&o.body)
.unwrap()
.keys
}
/// The site `s` declared again with `public` as its public repositories.
fn declare_public(state: &AppState, s: Site, public: &[&str]) {
state.registry.declare_estate(s.0, site_of(s, public));
}
const ALL: &[String] = &[];
fn only(g: &str) -> Vec<String> {
vec![g.to_string()]
}
fn as_operator<T>(r: T) -> tonic::Request<T> {
let mut req = tonic::Request::new(r);
req.extensions_mut().insert(crate::auth::Operator);
req
}
fn ack(state: &AppState, seq: u64, ok: bool, detail: &str) {
let g = state.fleet.guardian().unwrap();
let report = monetize_embed::fleet::Report {
acked: vec![monetize_embed::fleet::OrderAck {
seq,
ok,
detail: detail.into(),
receipt_json: String::new(),
}],
..Default::default()
};
g.store
.record_report("gunnar-rs", "main", state.now(), &report)
.unwrap();
}
fn status_of(state: &Arc<AppState>) -> pb::EstateOrderStatusResponse {
let svc = EstateOrderService(state.clone());
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
rt.block_on(svc.status(as_operator(pb::EstateOrderStatusRequest {
company: "gunnar-rs".into(),
actor_ticket: Vec::new(),
})))
.unwrap()
.into_inner()
}
/// ★ **Nothing to feed is refused by name** — no relay and no public repositories: nothing is
/// queued; the relay ASKED of a box that holds none (or half of one) is refused naming the half
/// it lacks, never a value; a relay that does not parse, and a group this box does not feed, too.
#[test]
fn nothing_to_feed_and_a_box_with_no_relay_are_refused_by_name_and_queue_nothing() {
let (state, ..) = laid_site("refeed-none", None);
match refeed::feed(&state, "gunnar-rs", ALL) {
Err(StartRefusal::NotNow(w)) => assert!(
w.starts_with("[site-refeed-none]")
&& w.contains("sold_smtp_url")
&& w.contains("public_repositories"),
"{w}"
),
other => panic!("{other:?}"),
}
match refeed::feed(&state, "gunnar-rs", &only("mail_relay")) {
Err(StartRefusal::NotNow(w)) => assert!(
w.starts_with("[site-mail-relay-none]") && w.contains("sold_smtp_url"),
"{w}"
),
other => panic!("{other:?}"),
}
// RA5-18: asked by name, a site that declares none is fed none public (never refused).
let (holger, ..) = laid_site_of("refeed-none-holger", HOLGER, None);
let asked =
refeed::feed(&holger, "holger-rs", &only("public_repositories")).expect("none public, fed");
assert!(
asked.words.contains("no repository public"),
"{}",
asked.words
);
assert_eq!(
relay_orders(&holger, "holger-rs")
.iter()
.map(body_of)
.collect::<Vec<_>>(),
vec![BTreeMap::from([(
"public_repositories".to_string(),
String::new()
)])]
);
match refeed::feed(&state, "gunnar-rs", &only("make_coffee")) {
Err(StartRefusal::BadName(w)) => assert!(
w.starts_with("[site-refeed-unknown]") && w.contains("make_coffee"),
"{w}"
),
other => panic!("{other:?}"),
}
assert!(
relay_orders(&state, "gunnar-rs").is_empty(),
"nothing queued"
);
let (state, ..) = laid_site("refeed-half", Some((URL, "")));
match refeed::feed(&state, "gunnar-rs", &only("mail-relay")) {
Err(StartRefusal::NotNow(w)) => assert!(
w.starts_with("[site-mail-relay-none]")
&& w.contains("sold_smtp_from")
&& !w.contains(TOKEN),
"{w}"
),
other => panic!("{other:?}"),
}
assert!(
relay_orders(&state, "gunnar-rs").is_empty(),
"nothing queued"
);
let (state, ..) = laid_site("refeed-bad", Some(("ftp://nope", FROM)));
match refeed::feed(&state, "gunnar-rs", ALL) {
Err(StartRefusal::BadName(w)) => assert!(w.starts_with("[site-mail-relay-bad]"), "{w}"),
other => panic!("{other:?}"),
}
assert!(
relay_orders(&state, "gunnar-rs").is_empty(),
"nothing queued"
);
match refeed::feed(&state, "no-such-site", ALL) {
Err(StartRefusal::NotFound(_)) => {}
other => panic!("{other:?}"),
}
}
/// ★ **A laid site's boxes are fed the box's relay as ONE signed refeed each** — the main and
/// the twin, under the site's LABEL: the body is the relay in the lay's own keys; the words and
/// the history name the keys, its host and port and the orders' seqs, never the token; a newer
/// refeed supersedes an unpulled older one.
#[test]
fn a_laid_sites_boxes_are_fed_the_boxes_relay_as_a_signed_refeed() {
let (state, _pay, _cloud, _kit, _dir, clock, mails) =
laid_site("refeed-relay", Some((URL, FROM)));
let before = mails.count("estate.ready");
let a = refeed::feed(&state, "gunnar-rs", ALL).expect("fed");
assert!(
a.words.contains("relay.mock.invalid:465")
&& !a.words.contains(TOKEN)
&& a.words.contains(&a.asked.to_string()),
"{}",
a.words
);
let orders = relay_orders(&state, "gunnar-rs");
assert_eq!(orders.len(), 1, "one signed order for gunnar-rs's main");
assert_eq!(
orders_for(&state, "gunnar-rs", "twin").len(),
1,
"and one for its twin"
);
assert!(
relay_orders(&state, "gunnarrs").is_empty(),
"never under the run's company name"
);
let o = &orders[0];
assert_eq!(o.seq, a.asked);
let pk =
ed25519_dalek::VerifyingKey::from_bytes(&state.signer_for("gunnar").public_key()).unwrap();
monetize_embed::fleet::verify_order(
o,
&pk,
("gunnar", "gunnar-rs", "main"),
clock.load(Ordering::SeqCst),
0,
)
.expect("signed for gunnar-rs's main");
let keys = body_of(o);
assert_eq!(
keys,
BTreeMap::from([
("secret.smtp_url".to_string(), URL.to_string()),
("secret.smtp_from".to_string(), FROM.to_string())
]),
"no public_repositories declared: the relay alone"
);
let r: monetize_embed::fleet::Refeed = serde_json::from_str(&o.body).unwrap();
assert!(
!format!("{r:?}").contains(TOKEN),
"the body's Debug names the keys only"
);
let run = state.estates.get("gunnarrs").unwrap();
let fed: Vec<_> = run
.history
.iter()
.filter(|t| t.note.contains("(refeed)"))
.collect();
assert!(
fed.len() == 1
&& fed.iter().all(|t| !t.note.contains(TOKEN)
&& t.note.contains("relay.mock.invalid:465")
&& t.note.contains("secret.smtp_url")
&& t.note.contains("gunnar-rs's main")),
"{:#?}",
run.history
);
assert_eq!(
mails.count("estate.ready"),
before,
"the shop mails nothing"
);
let again = refeed::feed(&state, "gunnar-rs", ALL).expect("fed again");
let orders = relay_orders(&state, "gunnar-rs");
assert_eq!(
orders.len(),
1,
"the newer supersedes the unpulled older one"
);
assert!(orders[0].seq > o.seq && orders[0].seq == again.asked);
}
/// ★ **NIGHT-PUBREPO through the same refeed**: a Holger site (holger.rs) whose declaration names
/// public repositories LATER than its lay is fed them again (`public_repositories = "crates,npm"`,
/// the lay's own key), with the relay or alone (`--only public_repositories`).
#[test]
fn a_sites_public_repositories_reach_its_laid_boxes_through_the_same_refeed() {
let (state, ..) = laid_site_of("refeed-public", HOLGER, Some((URL, FROM)));
declare_public(&state, HOLGER, &["crates", "npm"]);
let a = refeed::feed(&state, "holger-rs", ALL).expect("fed");
assert!(
a.words.contains("public_repositories crates,npm")
&& a.words.contains("relay.mock.invalid:465")
&& !a.words.contains(TOKEN),
"{}",
a.words
);
let keys = body_of(&relay_orders(&state, "holger-rs")[0]);
assert_eq!(
keys.get("public_repositories").map(String::as_str),
Some("crates,npm")
);
assert_eq!(keys.get("secret.smtp_url").map(String::as_str), Some(URL));
assert_eq!(
body_of(&orders_for(&state, "holger-rs", "twin")[0]),
keys,
"the twin is fed the same"
);
let p = refeed::feed(&state, "holger-rs", &only("public_repositories")).expect("fed alone");
let keys = body_of(&relay_orders(&state, "holger-rs")[0]);
assert_eq!(
keys,
BTreeMap::from([("public_repositories".to_string(), "crates,npm".to_string())]),
"only what was asked: {}",
p.words
);
// A box with no relay still feeds a site its public repositories.
let (state, ..) = laid_site_of("refeed-public-only", HOLGER, None);
declare_public(&state, HOLGER, &["crates"]);
refeed::feed(&state, "holger-rs", ALL).expect("the public list alone");
assert_eq!(
body_of(&relay_orders(&state, "holger-rs")[0]),
BTreeMap::from([("public_repositories".to_string(), "crates".to_string())])
);
}
/// ★ **A Gunnar site is never fed `public_repositories`** (OX-WIRED 2026-10-28): a Gunnar box
/// takes the mail relay's keys again and refuses a refeed with any other key WHOLE (gunnar-repair
/// `order::kind::REFEED_KEYS`), so the relay would never be kept either. Its product's facts say
/// it takes none (`Facts::public_repositories = Some(false)`): a Gunnar site that declares public
/// repositories anyway is fed its relay alone, `--only public_repositories` is refused by name
/// and queues nothing, and its lay feeds its boxes none. A Holger site's lay still carries them.
#[test]
fn a_gunnar_sites_boxes_are_never_fed_public_repositories_at_lay_or_in_a_refeed() {
let (state, _pay, _cloud, kit, ..) = laid_declared(
"refeed-gunnar-public",
GUNNAR,
&["crates"],
Some((URL, FROM)),
);
let laid = kit
.sites
.lock()
.unwrap()
.last()
.cloned()
.expect("the site's lay feed");
assert!(
laid.public_repositories.is_empty(),
"the lay feeds a Gunnar site's boxes no public_repositories: {:?}",
laid.public_repositories
);
let a = refeed::feed(&state, "gunnar-rs", ALL).expect("the relay is fed");
assert!(!a.words.contains("public_repositories"), "{}", a.words);
let keys = body_of(&relay_orders(&state, "gunnar-rs")[0]);
assert_eq!(
keys,
BTreeMap::from([
("secret.smtp_url".to_string(), URL.to_string()),
("secret.smtp_from".to_string(), FROM.to_string())
]),
"the relay's keys alone, as a Gunnar box takes them"
);
assert_eq!(
body_of(&orders_for(&state, "gunnar-rs", "twin")[0]),
keys,
"the twin is fed the same"
);
let before = relay_orders(&state, "gunnar-rs")[0].seq;
match refeed::feed(&state, "gunnar-rs", &only("public_repositories")) {
Err(StartRefusal::NotNow(w)) => assert!(
w.starts_with("[site-refeed-not-taken]") && w.contains("public_repositories"),
"{w}"
),
other => panic!("{other:?}"),
}
assert_eq!(
relay_orders(&state, "gunnar-rs")[0].seq,
before,
"nothing queued"
);
// A Holger site declared the same way is fed its list at lay.
let (_state, _pay, _cloud, kit, ..) =
laid_declared("refeed-holger-public-lay", HOLGER, &["crates"], None);
let laid = kit
.sites
.lock()
.unwrap()
.last()
.cloned()
.expect("the site's lay feed");
assert_eq!(
laid.public_repositories,
["crates"],
"a Holger site's lay carries its public repositories"
);
}
/// ★ **`site status` says the primary's answer**: not answered, refused with its reason, then
/// kept — the newest answered order's seq, whether it was kept, the words with every address
/// masked.
#[test]
fn the_status_says_the_primarys_answer_to_the_refeed() {
let (state, ..) = laid_site("refeed-status", Some((URL, FROM)));
let s = status_of(&state);
assert_eq!(
(s.refeed_answered, s.refeed_kept, s.refeed_words.as_str()),
(0, false, ""),
"nothing fed yet"
);
let svc = EstateOrderService(state.clone());
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
let r = rt
.block_on(svc.refeed(as_operator(pb::EstateOrderRefeedRequest {
estate: "gunnar-rs".into(),
only: Vec::new(),
})))
.expect("fed")
.into_inner();
assert!(r.asked > 0 && !r.words.contains(TOKEN), "{}", r.words);
let s = status_of(&state);
assert_eq!((s.refeed_answered, s.refeed_kept), (0, false));
assert!(s.refeed_words.contains("not pulled"), "{}", s.refeed_words);
ack(
&state,
r.asked,
false,
"order 9: Holger does not know the order kind \"refeed\"",
);
let s = status_of(&state);
assert_eq!(
(s.refeed_answered, s.refeed_kept),
(r.asked, false),
"{}",
s.refeed_words
);
assert!(
s.refeed_words.contains("refused") && s.refeed_words.contains("does not know"),
"{}",
s.refeed_words
);
let again = refeed::feed(&state, "gunnar-rs", ALL).unwrap();
ack(&state, again.asked, true, "kept secret.smtp_from, secret.smtp_url: the mail relay relay.mock.invalid:465 (implicit TLS) is in use: this box mails as estates@mock.invalid now");
let s = status_of(&state);
assert_eq!(
(s.refeed_answered, s.refeed_kept),
(again.asked, true),
"{}",
s.refeed_words
);
assert!(
s.refeed_words.contains("e***@mock.invalid")
&& !s.refeed_words.contains("estates@mock.invalid"),
"{}",
s.refeed_words
);
}
/// ★ **The operator's alone; a site not laid is refused by name.**
#[test]
fn the_service_hears_the_operator_alone_and_a_site_not_laid_is_refused() {
let (state, ..) = laid_site("refeed-operator", Some((URL, FROM)));
let svc = EstateOrderService(state.clone());
let rt = tokio::runtime::Builder::new_multi_thread()
.enable_all()
.build()
.unwrap();
let e = rt
.block_on(
svc.refeed(tonic::Request::new(pb::EstateOrderRefeedRequest {
estate: "gunnar-rs".into(),
only: Vec::new(),
})),
)
.unwrap_err();
assert_eq!(e.code(), tonic::Code::PermissionDenied, "{e:?}");
assert!(relay_orders(&state, "gunnar-rs").is_empty());
// A site ordered and not laid yet.
let rig = site_rig_with("refeed-not-laid", false);
site::start_site(
&rig.0,
"gunnar-rs",
"first-admin@mock.invalid",
&EstateSizes::default(),
)
.unwrap();
match refeed::feed(&rig.0, "gunnar-rs", ALL) {
Err(StartRefusal::NotNow(w)) => assert!(w.starts_with("[site-refeed-not-laid]"), "{w}"),
other => panic!("{other:?}"),
}
}
/// ★ **`EstateOrder.Refeed` over the wire** (OX-WIRED 2026-10-28): `monetize site refeed` reaches
/// the server as this call (the door's `POST /site/refeed`). Asked of the real router on a local
/// port with a real tonic client: the service bearer is refused by name and queues nothing; the
/// operator's bearer feeds the laid site's main its relay as one signed order.
#[test]
fn the_operators_refeed_over_grpc_feeds_the_main_and_the_service_bearer_is_refused_by_name() {
use monetize_proto::estate_order_client::EstateOrderClient;
const SERVICE: &str = "refeed-over-grpc-service-bearer-0123456789";
const OPERATOR: &str = "refeed-over-grpc-operator-bearer-0123456789";
let bearing = |bearer: &str| {
let mut req = tonic::Request::new(pb::EstateOrderRefeedRequest {
estate: "gunnar-rs".into(),
only: Vec::new(),
});
req.metadata_mut()
.insert("authorization", format!("Bearer {bearer}").parse().unwrap());
req
};
let (state, ..) = laid_site("refeed-over-grpc", Some((URL, FROM)));
let rt = tokio::runtime::Builder::new_multi_thread()
.worker_threads(2)
.enable_all()
.build()
.unwrap();
let s = state.clone();
let fed = rt.block_on(async move {
let server =
crate::testing::TestServer::spawn_with_operator(s.clone(), SERVICE, OPERATOR).await;
let mut c = EstateOrderClient::connect(server.endpoint())
.await
.expect("the router answers on its port");
let e = c
.refeed(bearing(SERVICE))
.await
.expect_err("the service bearer is not the operator");
assert_eq!(e.code(), tonic::Code::PermissionDenied, "{e:?}");
assert!(
e.message().contains("the operator's"),
"refused by name: {e:?}"
);
assert!(
relay_orders(&s, "gunnar-rs").is_empty(),
"a refused call queues nothing"
);
let fed = c
.refeed(bearing(OPERATOR))
.await
.expect("the operator's refeed")
.into_inner();
server.stop().await;
fed
});
assert!(fed.asked > 0 && !fed.words.contains(TOKEN), "{}", fed.words);
let orders = relay_orders(&state, "gunnar-rs");
assert_eq!(
orders.iter().map(|o| o.seq).collect::<Vec<_>>(),
vec![fed.asked],
"one signed order for the main, the one answered"
);
assert_eq!(
body_of(&orders[0])
.get("secret.smtp_url")
.map(String::as_str),
Some(URL)
);
}
/// ★ RA5-18 (OX-MONHUNT 2026-10-28): **a public repository is made private again.** The
/// operator takes `npm` out of `[estates.<site>] public_repositories` (it leaked something):
/// `site refeed --only public_repositories` feeds the EMPTY list (none public), where it was
/// refused by name and the box kept serving npm with no sign-in. Without `--only` an empty
/// declaration is still left out (a refeed of the relay alone changes no repository).
#[test]
fn a_cleared_declaration_is_fed_as_none_public_when_the_public_repositories_are_asked() {
let (state, ..) = laid_site_of("refeed-private-again", HOLGER, None);
declare_public(&state, HOLGER, &["npm"]);
refeed::feed(&state, "holger-rs", &only("public_repositories")).expect("npm fed public");
assert_eq!(
body_of(relay_orders(&state, "holger-rs").last().unwrap()),
BTreeMap::from([("public_repositories".to_string(), "npm".to_string())])
);
declare_public(&state, HOLGER, &[]);
let asked = refeed::feed(&state, "holger-rs", &only("public_repositories"))
.expect("the cleared list is fed, not refused");
assert!(
asked.words.contains("no repository public"),
"{}",
asked.words
);
let orders = relay_orders(&state, "holger-rs");
assert_eq!(
orders.len(),
1,
"the newer order superseded the unacked older one"
);
assert_eq!(
body_of(&orders[0]),
BTreeMap::from([("public_repositories".to_string(), String::new())]),
"none public"
);
match refeed::feed(&state, "holger-rs", ALL) {
Err(StartRefusal::NotNow(w)) => assert!(w.starts_with("[site-refeed-none]"), "{w}"),
other => panic!("without --only an empty declaration feeds nothing: {other:?}"),
}
}
/// The site `s` declared again with its public face `on` (TASKS-12's `public_site`).
fn declare_public_site(state: &AppState, s: Site, on: bool) {
let mut e = site_of(s, &[]);
e.public_site = on;
state.registry.declare_estate(s.0, e);
}
/// ★ **GRS-PUBLIC (live bug 2026-10-28): a site declared `public_site` AFTER its lay is fed its
/// public-site switch again.** gunnar.rs was laid before TASKS-12 (2026-10-25) declared its
/// public face, and a keep boot never feeds a front again: its console was never fed
/// `console_public_site = on`, so https://gunnar.rs/ asked every reader to log in. `site refeed
/// gunnar-rs --only public_site` (and a plain `site refeed`) feeds the declaration to its main and
/// twin as one signed `refeed` order (`console_public_site = on`); the main stores it as the
/// console's switch (gunnar `tests/public_site_refeed.rs`). Declared off again, `--only` feeds
/// `off`, and a plain refeed feeds nothing of it. Holger's boxes take it too (HOL-PUBSITE-FEED,
/// the test below).
#[test]
fn a_site_declared_public_after_its_lay_is_fed_its_public_site_switch_again() {
let (state, ..) = laid_site("refeed-public-site", None);
let laid = |state: &AppState| relay_orders(state, "gunnar-rs").last().map(body_of);
assert_eq!(laid(&state), None, "nothing fed yet");
let switch = |on: &str| BTreeMap::from([("console_public_site".to_string(), on.to_string())]);
declare_public_site(&state, GUNNAR, true);
let a = refeed::feed(&state, "gunnar-rs", &only("public_site"))
.expect("the declaration is fed again");
assert!(a.words.contains("console_public_site on"), "{}", a.words);
assert_eq!(
laid(&state),
Some(switch("on")),
"the main is fed the switch"
);
assert_eq!(
orders_for(&state, "gunnar-rs", "twin").last().map(body_of),
Some(switch("on")),
"the twin is fed the same"
);
// The operator's plain `site refeed gunnar-rs` (this box holds no relay for it): the switch alone.
refeed::feed(&state, "gunnar-rs", ALL).expect("a plain refeed feeds the declaration");
assert_eq!(laid(&state), Some(switch("on")));
// `public-site` is the same group (the CLI's dash).
refeed::feed(&state, "gunnar-rs", &only("public-site")).expect("the dashed name");
// Declared off again: asked by name it is fed `off`; a plain refeed feeds nothing of it.
declare_public_site(&state, GUNNAR, false);
refeed::feed(&state, "gunnar-rs", &only("public_site")).expect("off is fed by name");
assert_eq!(laid(&state), Some(switch("off")));
match refeed::feed(&state, "gunnar-rs", ALL) {
Err(StartRefusal::NotNow(w)) => assert!(w.starts_with("[site-refeed-none]"), "{w}"),
other => {
panic!("a plain refeed of a site not declared public feeds nothing of it: {other:?}")
}
}
}
/// ★ **HOL-PUBSITE-FEED (2026-11-01): a Holger site is fed its public-site switch again too**, as
/// Gunnar's is. holger.rs's console.public-site was stored nowhere, and `site refeed holger-rs
/// --only public_site` was refused `[site-refeed-not-taken]`: Holger's facts did not say
/// `public_site`. Now they do (holger-monetize-guest `lifecycle`), so the declaration reaches
/// Holger's main and twin as one signed `refeed` (`console_public_site = on | off`), which keep
/// it as the console's setting `console.public-site` (holger server-lib
/// `tests/a_refeed_keeps_the_consoles_public_site_switch.rs`). A product whose facts do not say
/// it is never fed it ([`crate::facts::Facts::takes_public_site`]).
#[test]
fn a_holger_site_declared_public_is_fed_its_public_site_switch_again() {
let (holger, ..) = laid_declared("refeed-public-site-holger", HOLGER, &["crates"], None);
let switch = |on: &str| BTreeMap::from([("console_public_site".to_string(), on.to_string())]);
declare_public_site(&holger, HOLGER, true);
let a = refeed::feed(&holger, "holger-rs", &only("public_site"))
.expect("Holger's boxes take the switch");
assert!(a.words.contains("console_public_site on"), "{}", a.words);
assert_eq!(
relay_orders(&holger, "holger-rs").last().map(body_of),
Some(switch("on")),
"the main is fed the switch"
);
assert_eq!(
orders_for(&holger, "holger-rs", "twin").last().map(body_of),
Some(switch("on")),
"the twin is fed the same"
);
declare_public_site(&holger, HOLGER, false);
refeed::feed(&holger, "holger-rs", &only("public_site")).expect("off is fed by name");
assert_eq!(
relay_orders(&holger, "holger-rs").last().map(body_of),
Some(switch("off"))
);
assert!(
!crate::facts::Facts::default().takes_public_site(),
"facts that do not say it are never fed it"
);
}