crates/monetize-server/src/estate_order/site.rs
//! **The OPERATOR-SITE ORDER** (owner 2026-10-13: "the shop must deploy gunnar.rs itself"):
//! the ONE box lays a declared operator site — `[estates.<label>] operator_site = true`,
//! `gunnar-rs` → gunnar.rs, www., git. — the way it lays a sold estate: the hold (the
//! operator's EUR 0.50, through the site's OWN vendor), the lay from the release's templates
//! or media, the shop's own installer, the DNS writer of the site's zone, the quick test, the
//! capture. Nothing here is a second mechanism: it is [`super::start_order`] and the same
//! job; what differs is data, the order's [`super::LayAt::root`] (A33-5), and who pays:
//!
//! * **Its names are the apex's own** ([`super::EstateOrderConfig::site_itself`]): a sold
//! estate is refused them, this run alone lays them.
//! * **It is bound to the site it already is.** The run's company IS the estate's label, so
//! its boxes pull as that label, the guardian knows it as that estate, and its tenants are
//! the site's. Its console is fed the site's own bearer at the ONE box — minted here at the
//! install ([`mint_bearer`]), kept by its digest only, newer than the enrolment's — and the
//! ticket key its primary offered is the site's ([`installed`]).
//! * **It is ordered by the operator** — `EstateOrder.OrderSite`, the operator bearer's alone
//! (the ONE box's console form, and the `monetize` CLI through the box's door): the estate,
//! the size (a ladder step) and the address the ready mail goes to; the answer names where
//! the operator pays. A site that stands (its boxes call home) is not laid over.
//!
//! No monetize runs on the laid site (ONE monetize): its vendor, its fleet keys and its
//! bearer stay the ONE box's.
use super::{phase, EstateRun, EstateSizes, LayAt, OrderedBy, SiteFeed, StartRefusal};
use crate::state::AppState;
/// A site whose box reported this recently STANDS: it is not laid over.
pub const STANDS_WITHIN_MS: u64 = 15 * 60_000;
/// **`site order`**: lay the declared operator site `estate` itself, at `sizes`, the ready
/// mail to `email`. Refused by name before anything is held: an estate that is not a declared
/// operator site, one that names no site, one whose boxes call home, one already ordered.
pub fn start_site(state: &AppState, estate: &str, email: &str, sizes: &EstateSizes) -> Result<EstateRun, StartRefusal> {
start_site_seeded(state, estate, email, sizes, "")
}
/// Pure: why `key` is not a seed's public key, or `None` — one OpenSSH ed25519 line.
pub fn seed_key_refusal(key: &str) -> Option<String> {
let key = key.trim();
let mut words = key.split_whitespace();
let ok = !key.contains('\n') && words.next() == Some("ssh-ed25519") && words.next().is_some_and(|b| b.len() >= 60 && b.bytes().all(|c| c.is_ascii_alphanumeric() || matches!(c, b'+' | b'/' | b'=')));
(!ok).then(|| "the seed key is one OpenSSH public line (`ssh-ed25519 AAAA… [comment]`), never a private key".to_string())
}
/// [`start_site`], naming the seed's PUBLIC key (`seed_key`, one OpenSSH line; empty: none):
/// the laid site knows it as the machine principal its declared repositories are seeded as.
pub fn start_site_seeded(state: &AppState, estate: &str, email: &str, sizes: &EstateSizes, seed_key: &str) -> Result<EstateRun, StartRefusal> {
start_site_back_to(state, estate, email, sizes, seed_key, "")
}
/// Pure: why `url` cannot be where the vendor's page sends the operator back, or `None` —
/// an absolute https URL with a host, no whitespace (empty is allowed: the vendor's own).
pub fn back_to_refusal(url: &str) -> Option<String> {
let url = url.trim();
if url.is_empty() {
return None;
}
let host = url.strip_prefix("https://").map(|r| r.split(['/', '?', '#']).next().unwrap_or(""));
match host {
Some(h) if !h.is_empty() && !url.chars().any(char::is_whitespace) => None,
_ => Some(format!("the return page {url:?} is not an https URL: the vendor's page sends the operator back there")),
}
}
/// [`start_site_seeded`], the vendor's page sending the operator back to `back_to` (the ONE
/// box's Sites page, as its console names it; empty: the vendor's own return page).
pub fn start_site_back_to(state: &AppState, estate: &str, email: &str, sizes: &EstateSizes, seed_key: &str, back_to: &str) -> Result<EstateRun, StartRefusal> {
start_site_paid(state, estate, email, sizes, seed_key, back_to, false).map(|(run, _)| run)
}
/// ★ **`site test-order`** (owner: "monetize must be automatic"): [`start_site_seeded`], the
/// hold paid SERVER-SIDE with the site's vendor's TEST payment method (Stripe's `pm_card_visa`,
/// as the test button pays), so a throwaway lay needs no browser. Refused by name — after the
/// site's own refusals, and BEFORE the vendor is asked anything — unless the site's vendor
/// holds a TEST key ([`test_card_of`]). No page is opened; the run is marked test. Answers the
/// run and the test card that holds it.
pub fn start_site_test(state: &AppState, estate: &str, email: &str, sizes: &EstateSizes, seed_key: &str) -> Result<(EstateRun, String), StartRefusal> {
start_site_paid(state, estate, email, sizes, seed_key, "", true)
}
/// ★ A33-4: **what a vendor's key is, read ONCE for every test-card check** (the test button's
/// verdict and `site test-order`'s card): what the vendor already knows of its key
/// ([`monetize_pay::Payment::livemode`]) and its test payment method, a blank one being none.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum KeyKind {
/// A LIVE key: real money, paid by a person at the vendor's page.
Live,
/// A TEST key, with the vendor's test payment method if it offers one.
Test(Option<String>),
/// A key that cannot say which it is: treated as live by every test path.
Unknown,
}
/// Pure on the vendor: its [`KeyKind`].
pub fn key_kind(vendor: monetize_pay::Vendor<'_>) -> KeyKind {
match vendor.livemode() {
Some(true) => KeyKind::Live,
Some(false) => KeyKind::Test(vendor.test_payer().filter(|p| !p.trim().is_empty())),
None => KeyKind::Unknown,
}
}
/// Pure on the vendor: **the TEST card a `site test-order` holds with** — the vendor's own test
/// payment method, on a key that says it is a TEST key. A LIVE key is refused by name, and so is
/// a key that cannot say which it is (refused like live: a test order never spends live money).
/// Reads only what the vendor already knows of its key ([`monetize_pay::Payment::livemode`]):
/// nothing is sent, and the key itself is never in the words.
pub fn test_card_of(vendor: monetize_pay::Vendor<'_>, estate: &str, instance: &str) -> Result<String, String> {
match key_kind(vendor) {
KeyKind::Test(Some(card)) => Ok(card),
KeyKind::Live => Err(format!("REFUSED [test-order-live-key] {estate}'s vendor {instance} holds a LIVE key: a test order is never paid on it (order it with `site order` and pay at the vendor's page). Nothing was asked of the vendor")),
KeyKind::Test(None) => Err(format!("REFUSED [test-order-no-test-card] {estate}'s vendor {instance} offers no test payment method: nothing can pay without a person. Nothing was asked of the vendor")),
KeyKind::Unknown => Err(format!("REFUSED [test-order-key-unknown] {estate}'s vendor {instance} cannot say whether its key is a test or a live key: refused like live. Nothing was asked of the vendor")),
}
}
/// [`test_card_of`] for the vendor `estate`'s orders are paid through (its own account, ST-5).
pub(crate) fn site_test_card(state: &AppState, estate: &str) -> Result<String, StartRefusal> {
let base = state.estates.cfg.as_ref().ok_or_else(|| StartRefusal::NotSold("this monetize sells no private estates ([estate_orders] is absent)".into()))?;
let terms = super::terms_on(state, base, Some(estate)).map_err(StartRefusal::NotSold)?;
let vendor = state.registry.find_vendor(&terms.vendor).ok_or_else(|| StartRefusal::NotSold(format!("REFUSED [test-order-no-vendor] {estate}'s vendor {:?} is not linked here: nothing was asked", terms.vendor)))?;
test_card_of(vendor, estate, &terms.vendor).map_err(StartRefusal::NotSold)
}
/// The one site order: the operator pays at the vendor's page (`test_card` false), or the
/// vendor's TEST card pays it server-side ([`start_site_test`]); answered with the card (empty:
/// none).
fn start_site_paid(state: &AppState, estate: &str, email: &str, sizes: &EstateSizes, seed_key: &str, back_to: &str, test_card: bool) -> Result<(EstateRun, String), StartRefusal> {
if let Some(why) = back_to_refusal(back_to) {
return Err(StartRefusal::BadName(why));
}
let estate = estate.trim();
let seed_key = seed_key.trim();
if !seed_key.is_empty() {
if let Some(why) = seed_key_refusal(seed_key) {
return Err(StartRefusal::BadName(why));
}
}
let Some(admin) = state.registry.operator_admin_of(estate) else {
return Err(StartRefusal::NotSold(format!("{estate:?} is not a declared operator site ([estates.<label>] operator_site = true with its owner): only the operator's own sites are laid by a site order")));
};
if state.registry.site_of(estate).is_none() {
return Err(StartRefusal::NotSold(format!("[estates.{estate}] names no site: a site order lays the site's own apex")));
}
if let Some(g) = state.fleet.guardian() {
let now = state.now();
let heard: Vec<String> = ["front", "main", "twin"].iter().map(|r| r.to_string()).filter(|r| g.store.box_record(estate, r).is_some_and(|b| b.heard_unix_ms > 0 && now.saturating_sub(b.heard_unix_ms) < STANDS_WITHIN_MS)).collect();
if !heard.is_empty() {
return Err(StartRefusal::NotNow(format!("{estate} stands: its {} called home in the last {} minutes — a site that runs is not laid over", heard.join(", "), STANDS_WITHIN_MS / 60_000)));
}
}
let company = company_of(estate);
if let Some(why) = monetize_cloud::lay::company_name_refusal(&company) {
return Err(StartRefusal::NotSold(format!("the site {estate} cannot be laid: as the cloud names an estate it is {company:?}, and {why}")));
}
if state.estates.get(&company).is_some_and(|r| !phase::is_gone(&r.phase)) {
return Err(StartRefusal::Taken(format!("{estate} is already ordered")));
}
// The key is judged LAST of the refusals and FIRST of anything the vendor is asked.
let test_payer = if test_card { site_test_card(state, estate)? } else { String::new() };
let by = OrderedBy::Operator { back_to: back_to.trim().to_string(), test_payer: test_payer.clone() };
super::start_order(state, &LayAt::root_of(estate, seed_key), &company, email, "", &admin, sizes, &by).map(|run| (run, test_payer))
}
/// ★ A33-5: **why `company` cannot lay the ROOT of `estate` for `account`**, or `None` — the
/// one check [`super::start_order`] makes of a root: `estate` is a declared operator site,
/// `account` is its admin and `company` is the site's own label as the cloud names an estate.
pub fn root_refusal(state: &AppState, estate: &str, company: &str, account: &str) -> Option<String> {
let estate = estate.trim();
match state.registry.operator_admin_of(estate) {
None => Some(format!("{estate:?} is not a declared operator site ([estates.<label>] operator_site = true with its owner): only the operator's own sites are laid at their root")),
Some(admin) if admin != account.trim() => Some(format!("only the admin of {estate} orders its root")),
Some(_) if company != company_of(estate) => Some(format!("{estate}'s root is laid as {:?}, never as {company:?}", company_of(estate))),
Some(_) => None,
}
}
/// Pure: **the site's label as the cloud names an estate** — its letters and digits
/// (`gunnar-rs` → `gunnarrs`): the provider's estate rule takes no hyphen, and the rule is
/// the signed cloud guest's own. The run is kept under it; the site's label stays its
/// [`EstateRun::estate`] and its fleet name.
pub fn company_of(estate: &str) -> String {
estate.chars().filter(|c| c.is_ascii_lowercase() || c.is_ascii_digit()).collect()
}
/// **The site's own bearer at the ONE box, minted for this lay**: 32 random bytes (hex), known
/// to the fleet by its digest for [`crate::fleet::BEARER_LIFE_MS`], the digest kept on the
/// run. The bearer itself goes to the installer's feed and nowhere else.
pub fn mint_bearer(state: &AppState, run: &mut EstateRun) -> Result<SiteFeed, String> {
let bearer: String = crate::seal::random32()?.iter().map(|b| format!("{b:02x}")).collect();
let now = state.now();
run.site_bearer_sha256 = crate::fleet::bearer_digest(&bearer);
run.site_bearer_at_ms = now.max(1);
run.site_bearer_until_ms = now.saturating_add(crate::fleet::BEARER_LIFE_MS);
state.fleet.know_bearer_until(&run.site_bearer_sha256, &run.estate, run.site_bearer_until_ms);
Ok(SiteFeed { bearer, ..box_feed(state, run) })
}
/// **The site's feed as its declaration says it now, with no bearer** (RA5-17): what a box of
/// the site laid again is fed (the guardian's relay, a plan change) — its product, its label,
/// its seed key, its public face and CLI hole, its public repositories.
pub fn box_feed(state: &AppState, run: &EstateRun) -> SiteFeed {
let product = state.registry.product_of_estate(&run.estate).unwrap_or_else(|| super::instance_product(state));
let public_site = state.registry.public_site(&run.estate);
let cli_hole_public = state.registry.cli_hole_public(&run.estate);
// Only to boxes that take them (the product's facts: a Gunnar box takes none).
let public_repositories = if super::refeed::takes_public_repositories(&product) { state.registry.public_repositories(&run.estate) } else { Vec::new() };
SiteFeed { bearer: String::new(), product, label: run.estate.clone(), seed_key: run.site_seed_key.clone(), public_site, cli_hole_public, public_repositories }
}
/// **The site's install PASSed**: the ticket key its primary offered is the site's, as an
/// enrolled estate's notice would have delivered it. Answers the line for the order's log.
pub fn installed(state: &AppState, run: &mut EstateRun, ticket_key: &str) -> String {
let key = ticket_key.trim().to_ascii_lowercase();
if key.is_empty() {
return format!("the installer named no ticket key for {}: its accounts' tickets are not checked until its estate delivers one", run.estate);
}
run.site_ticket_key = key;
let line = deliver_key(state, run).unwrap_or_else(|| format!("{}'s ticket key is the one its primary offered", run.estate));
// Said in the box's log too: the operator reads there that the site's accounts are checked.
eprintln!("monetize-server: site order {}: {line}", run.estate);
line
}
fn deliver_key(state: &AppState, run: &EstateRun) -> Option<String> {
let product = state.registry.product_of_estate(&run.estate)?;
match state.registry.deliver_appliance_key(&product, &run.estate, &run.site_ticket_key) {
Ok(line) => line,
Err(refused) => Some(refused),
}
}
/// The site-order runs that still stand for something (not gone).
fn standing(state: &AppState) -> Vec<EstateRun> {
state.estates.all().into_iter().filter(|r| r.site_order && !phase::is_gone(&r.phase)).collect()
}
/// **Whether `estate` was laid here with a bearer minted after `since_ms`** — then the
/// shop's bearer for it stands over an older enrolment's.
pub fn bearer_newer_than(state: &AppState, estate: &str, since_ms: u64) -> bool {
standing(state).iter().any(|r| r.estate == estate && !r.site_bearer_sha256.is_empty() && r.site_bearer_at_ms > since_ms)
}
/// **Whether `estate` was ordered here (a site order that still stands) after `since_ms`**:
/// from then on the shop keys its boxes, not an older join record.
pub fn laid_since(state: &AppState, estate: &str, since_ms: u64) -> bool {
// An ADOPTED site was laid by its kit: its join record keeps keying its boxes.
standing(state).iter().any(|r| r.estate == estate && r.ordered_at_ms > since_ms && !super::adopt::is_adopted(r))
}
/// **Restate what the laid sites hold** (every tick, and so after a restart): each one's
/// bearer digest and its ticket key. Both are idempotent.
pub fn reassert(state: &AppState) {
for run in standing(state) {
if !run.site_bearer_sha256.is_empty() {
state.fleet.know_bearer_until(&run.site_bearer_sha256, &run.estate, run.site_bearer_until_ms);
}
if !run.site_ticket_key.is_empty() {
if let Some(line) = deliver_key(state, &run) {
eprintln!("monetize-server: site order {}: {line}", run.estate);
}
}
}
}
/// The sizes of the ladder step named `size` (any case); empty: the shape's own.
pub fn sizes_of(state: &AppState, size: &str) -> Result<EstateSizes, String> {
let size = size.trim();
if size.is_empty() {
return Ok(EstateSizes::default());
}
let cfg = state.estates.cfg.as_ref().ok_or("this monetize sells no estates ([estate_orders] is absent)")?;
cfg.ladder.iter().find(|s| s.name.eq_ignore_ascii_case(size)).map(|s| EstateSizes { front_plan: s.front_plan.clone(), main_plan: s.main_plan.clone(), main_data_gib: s.main_data_gib, ..Default::default() }).ok_or_else(|| format!("{size:?} is not a step of the ladder ({})", cfg.ladder.iter().map(|s| s.name.as_str()).collect::<Vec<_>>().join(", ")))
}
/// [`sizes_of`] on the ladder of the site `estate` ([`super::terms_on`]): a site of another
/// product is sized on its own product's ladder (lane L18). A site the terms refuse: the shop's.
pub fn sizes_of_on(state: &AppState, estate: Option<&str>, size: &str) -> Result<EstateSizes, String> {
let size = size.trim();
if size.is_empty() {
return Ok(EstateSizes::default());
}
let base = state.estates.cfg.as_ref().ok_or("this monetize sells no estates ([estate_orders] is absent)")?;
let ladder = super::terms_on(state, base, estate).map(|t| t.ladder).unwrap_or_else(|_| base.ladder.clone());
ladder.iter().find(|s| s.name.eq_ignore_ascii_case(size)).map(|s| s.sizes()).ok_or_else(|| format!("{size:?} is not a step of the ladder ({})", ladder.iter().map(|s| s.name.as_str()).collect::<Vec<_>>().join(", ")))
}
/// **One operator site, as the operator's order form shows it**: what an order needs of it —
/// every field already fed from the box's declaration — and where its order stands.
#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub struct SiteView {
pub estate: String,
pub domain: String,
pub vendor: String,
pub first_admin: String,
pub dns_words: String,
pub dns_writes: bool,
pub cloud_words: String,
/// `none`, an order's state word, or `stands`.
pub state: String,
pub words: String,
pub checkout_url: String,
/// Why it cannot be ordered now; empty: it can.
pub why_not: String,
/// Whether a terminate may end it (`[estates.<label>] terminable`).
pub terminable: bool,
/// **Whether "Check again" is offered** (F5): its setup failed (`install_failed`, `owed`) and
/// the machines its run names still stand, so every box can be asked its pair status.
pub recheckable: bool,
/// Its run's own reason and since when ([`super::EstateRun::why_said`]); empty: none.
pub why: String,
pub why_since: String,
/// ★ A33-6: what it costs, in words — its run's amount, else the operator's own price.
pub price_words: String,
}
/// Pure: **whether a site offers Terminate now** — something stands to end: its order laid
/// it (`laid` = `Some(true)`), or its boxes call home (`heard`). Never on a site that was never
/// laid (live 2026-10-14: Terminate shown on a site whose order was owed before any lay).
pub fn terminable_now(laid: Option<bool>, heard: bool) -> bool {
heard || laid == Some(true)
}
/// **Whether anything of `run` stands to be ended**: what its run names (laid), boxes that call
/// home (`heard`), or — for a setup that failed (`owed`, `failed`) whose run names nothing any
/// more — anything still billed under its reference at its cloud (F3, 2026-10-20: an owed
/// site's machines stood and no Terminate was offered).
pub fn anything_stands(state: &AppState, run: &EstateRun, heard: bool) -> bool {
if terminable_now(run.laid.as_ref().map(|_| true), heard) || run.phase == phase::TERMINATING {
return true;
}
if !matches!(run.phase.as_str(), phase::OWED | phase::FAILED) {
return false;
}
let Some(base) = state.estates.cfg.as_ref() else { return false };
let Ok(cfg) = super::terms_of(state, base, run) else { return false };
state.registry.find_cloud(&cfg.cloud).and_then(|c| monetize_cloud::ask::orphans_for(&c, std::slice::from_ref(&run.reference)).ok()).is_some_and(|left| !left.is_empty())
}
/// The ladder's step names, smallest first: the sizes a site is ordered at.
pub fn sizes_on_offer(state: &AppState) -> Vec<String> {
state.estates.cfg.as_ref().map(|c| c.ladder.iter().map(|s| s.name.clone()).collect()).unwrap_or_default()
}
/// **The words for the site `label`'s OWN product** (live 2026-10-19: the Holger site
/// test3-holger-rs read "Gunnar is being installed"): a site of the shop's product takes the
/// shop's words ([`super::lifecycle::words_of`]); a site of another product takes its
/// lifecycle's (`holger`, else its family before the first `-`), else neutral words.
pub fn words_for(state: &AppState, label: &str) -> super::lifecycle::ProductWords {
let cfg = state.estates.cfg.as_ref();
let own = state.registry.product_of_estate(label).map(|p| p.trim().to_string()).filter(|p| !p.is_empty());
match own {
Some(own) if cfg.is_none_or(|c| c.product.trim() != own) => super::lifecycle::find(&own)
.or_else(|| own.split_once('-').and_then(|(family, _)| super::lifecycle::find(family)))
.map(|l| l.words())
.unwrap_or_else(super::lifecycle::ProductWords::neutral),
_ => super::lifecycle::words_of(cfg),
}
}
/// **The operator's sites** (`[estates.<label>] operator_site = true`), in label order.
/// The state a delivered site reads while its shop cannot answer it (M-FOLLOW 1).
pub const UNJOINED: &str = "unjoined";
/// **Why a delivered site's shop cannot answer it**, or `None` (M-FOLLOW 1, prod 2026-10-26:
/// `site list` said gunnar-rs `ready` while its join record was put aside and its shop answered
/// 503). A site's estate-facing calls (its shop's ladder, its signups) open only with its ONE
/// live bearer here: the one this box minted at its lay ([`mint_bearer`], restated every tick),
/// or the one its join record holds (`joined/<site>.json`, an adopted or kit-enrolled site).
/// None live, revoked or expired: its front's calls open nothing, so it is not `ready`.
pub fn shop_cannot_answer(state: &AppState, run: &EstateRun) -> Option<String> {
if !run.site_order || !matches!(run.phase.as_str(), phase::CAPTURED | phase::GRACE) {
return None;
}
let now = state.now();
if !run.site_bearer_sha256.is_empty() && now < run.site_bearer_until_ms {
return None;
}
let record = format!("{}/{}.json", crate::fleet::JOINED_REL, run.estate);
match state.fleet.bearer_of(&run.estate) {
Some(b) if b.revoked_unix_ms > 0 => Some(format!("its bearer was revoked on {}, so its front's calls open nothing here", super::iso_date(b.revoked_unix_ms))),
Some(b) if now >= b.until_unix_ms => Some(format!("its bearer expired on {}, so its front's calls open nothing here", super::iso_date(b.until_unix_ms))),
Some(_) => None,
None if super::adopt::is_adopted(run) => Some(format!("no join record ({record}) holds its bearer here: it is not taken yet, or it was put aside")),
None if !run.site_bearer_sha256.is_empty() => Some(format!("the bearer this box minted at its lay expired on {}, and no join record ({record}) holds another", super::iso_date(run.site_bearer_until_ms))),
None => Some(format!("this box holds no bearer for it: none was minted at its lay, and no join record ({record}) holds one")),
}
}
/// **The operator's view of a site run, held back from `ready` while its shop cannot answer**
/// ([`shop_cannot_answer`]): `site list` and `site status` read the same.
pub fn operator_view_held(state: &AppState, run: &EstateRun, view: (String, String, String)) -> (String, String, String) {
let (st, words, url) = view;
if st != "ready" {
return (st, words, url);
}
match shop_cannot_answer(state, run) {
None => (st, words, url),
Some(why) => {
let how = if super::adopt::is_adopted(run) { "adopted" } else { "laid" };
(UNJOINED.to_string(), format!("{} is {how}, but its shop cannot answer: {why}. It reads ready again once the guardian takes its join record (a feed that serves its product, or its kit's enrolment again).", run.estate), url)
}
}
}
pub fn sites(state: &AppState) -> Vec<SiteView> {
let cfg = state.estates.cfg.as_ref();
let now = state.now();
state
.registry
.declared_estates()
.into_iter()
.filter(|(_, e)| e.operator_site)
.map(|(label, e)| {
let dns = state.estates.dns_on(&label);
let dns_writes = dns.writes();
let dns_words = if dns_writes { "this box's one DNS token writes its zone".to_string() } else { dns.write(&[]).err().filter(|w| !w.is_empty()).unwrap_or_else(|| "this box's DNS token does not write its zone".into()) };
let run = state.estates.get(&label).filter(|r| r.site_order && !phase::is_gone(&r.phase));
let heard = state.fleet.guardian().is_some_and(|g| ["front", "main", "twin"].iter().any(|r| g.store.box_record(&label, r).is_some_and(|b| b.heard_unix_ms > 0 && now.saturating_sub(b.heard_unix_ms) < STANDS_WITHIN_MS)));
let domain = e.site.trim().to_string();
let stands = run.as_ref().map_or(heard, |r| anything_stands(state, r, heard));
let (st, words, checkout_url) = match &run {
Some(run) => {
let (st, words, _) = operator_view_held(state, run, run.operator_view_as(&domain, &words_for(state, &label)));
// An install that makes no progress names why (test3-holger-rs 2026-10-22).
let mut words = super::install_why::with_why(state, run, words);
// F2: a stopped install says how its boxes go — or that it is protected.
// F3: so does a setup that failed after payment while its boxes stand.
if st == super::INSTALL_FAILED || (st == "owed" && stands) {
let how = if e.terminable { "Terminate removes its boxes.".to_string() } else { format!("{}.", super::PROTECTED_FAILED) };
words = format!("{words} {how}");
}
(st, words, if run.phase == phase::ORDERED { run.checkout_url.clone() } else { String::new() })
}
None if heard => ("stands".to_string(), "It runs: its boxes call home.".to_string(), String::new()),
None => ("none".to_string(), "Not laid by this box.".to_string(), String::new()),
};
let why_not = if run.is_some() {
"it is already ordered".to_string()
} else if heard {
"it stands: a site that runs is not laid over".to_string()
} else if domain.is_empty() {
"it names no domain".to_string()
} else if !dns_writes {
dns_words.clone()
} else if cfg.is_none() {
"this box lays no estates".to_string()
} else {
String::new()
};
SiteView {
estate: label,
domain,
vendor: e.vendor.clone(),
first_admin: e.owner.trim().to_string(),
dns_words,
dns_writes,
cloud_words: cfg.map(|c| format!("{} · {}", c.cloud, c.zone)).unwrap_or_default(),
state: st,
words,
checkout_url,
why_not,
// Terminate ends what STANDS, in a phase a terminate takes ([`super::terminate::
// phase_allows`], the server's own rule): a site this box never laid (its order
// failed before the lay, or is not paid yet) and of which nothing stands has
// nothing to end — its order is settled (retry, refund), not terminated; an owed
// site whose boxes stand is (F3). An adopted site is ended by its kit
// ([`super::terminate`] refuses it by name).
// F5: a failed setup whose machines stand: every box can be asked again.
recheckable: stands && run.as_ref().is_some_and(super::recheckable),
terminable: e.terminable && stands && run.as_ref().is_none_or(|r| super::terminate::phase_allows(&r.phase) && !super::adopt::is_adopted(r)),
why: run.as_ref().and_then(|r| r.why_said()).map(|w| w.0).unwrap_or_default(),
why_since: run.as_ref().and_then(|r| r.why_said()).map(|w| w.1).unwrap_or_default(),
price_words: run.as_ref().filter(|r| r.amount.minor > 0).map(|r| r.amount.in_words()).unwrap_or_else(|| monetize_pay::Money { minor: super::OPERATOR_TEST_MINOR, currency: monetize_pay::Currency::Eur }.in_words()),
}
})
.collect()
}