Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/monetize

crates/monetize-server/src/services/usage.rs

use std::sync::Arc;

use monetize::fleet::Oversell;
use monetize::ledger::Holding;
use monetize::trend::{self, Trend};
use monetize_cloud::lay::{same_resource, LaidEstate};
use monetize_cloud::{Cloud, Owned};
use monetize_product::{Servable, TenantId};
use monetize_proto::usage_server::Usage;
use monetize_proto::{self as pb};
use tonic::{Request, Response, Status};

use super::{blocking, product_or_not_found};
use crate::convert::usage_to_pb;
use crate::estate_order::{phase, EstateRun};
use crate::state::AppState;
use crate::store::StoreError;

pub struct UsageService(pub Arc<AppState>);

fn store_err(e: StoreError) -> Status {
    Status::internal(format!("usage store: {e}"))
}

/// **The window a rate is quoted over when the caller names none: 30 days.**
///
/// `UI.md` renders `Full in ~9 weeks (12 GiB/wk, last 30 d)` — the window is on
/// the screen beside the number, so it has to be a stated constant rather than
/// whatever the store happens to hold. A month is long enough that one push does
/// not own the answer and short enough that last quarter's habits do not.
pub const DEFAULT_WINDOW_MS: u64 = 30 * 24 * 60 * 60 * 1000;

/// **How many readings one trend fold will look at per tenant.** A 30-day window
/// at the default fifteen-minute tick is ~2 880 readings; the ceiling is above
/// that so the ordinary case is never silently truncated, and below
/// `UsageStore::HISTORY_CEILING` so a fleet fold over many tenants cannot be
/// asked to decode an unbounded amount.
const TREND_READINGS: usize = 4_000;

/// The window's start: `window_ms` back from now, with 0 meaning
/// [`DEFAULT_WINDOW_MS`]. Returned alongside so the response can echo what was
/// actually applied.
fn window(state: &AppState, window_ms: u64) -> (u64, u64) {
    let window_ms = if window_ms == 0 {
        DEFAULT_WINDOW_MS
    } else {
        window_ms
    };
    (state.now().saturating_sub(window_ms), window_ms)
}

/// One folded rate on the wire. **The `enough_history` arm is the whole point**:
/// it is how "I do not know" reaches the console as something other than a zero.
fn trend_to_pb(
    t: Trend,
    window_ms: u64,
    measured_tenants: u64,
    unmeasured_tenants: u64,
) -> pb::TrendResponse {
    let base = pb::TrendResponse {
        enough_history: false,
        per_week: 0.0,
        confidence: String::new(),
        largest_step_share: 0.0,
        readings: 0,
        span_ms: 0,
        needed_span_ms: trend::MIN_SPAN_MS,
        window_ms,
        first_at_unix_ms: 0,
        last_at_unix_ms: 0,
        measured_tenants,
        unmeasured_tenants,
    };
    match t {
        Trend::NotEnoughHistory(n) => pb::TrendResponse {
            readings: n.readings as u64,
            span_ms: n.span_ms,
            needed_span_ms: n.needed_span_ms,
            ..base
        },
        Trend::Rate(r) => pb::TrendResponse {
            enough_history: true,
            per_week: r.per_week,
            confidence: r.confidence().name().into(),
            largest_step_share: r.largest_step_share(),
            readings: r.readings as u64,
            span_ms: r.span_ms,
            first_at_unix_ms: r.first_at_unix_ms,
            last_at_unix_ms: r.last_at_unix_ms,
            ..base
        },
    }
}

/// **One [`monetize_product::ActivityDay`] → one `ActivityDay` on the wire.**
/// The one writer of that mapping.
///
/// The meters go out sorted by name because `BTreeMap` iteration is, and a
/// repeated field whose order changed between two identical reads would make
/// every consumer's diff noisy for nothing.
fn activity_day_to_pb(day: &monetize_product::ActivityDay) -> pb::ActivityDay {
    pb::ActivityDay {
        day_unix_ms: day.day_unix_ms,
        meters: day
            .meters
            .iter()
            .map(|(name, value)| pb::Meter {
                name: name.clone(),
                value: *value,
            })
            .collect(),
    }
}

#[tonic::async_trait]
impl Usage for UsageService {
    async fn read(
        &self,
        req: Request<pb::ReadUsageRequest>,
    ) -> Result<Response<pb::ReadUsageResponse>, Status> {
        let r = req.into_inner();
        blocking(&self.0, move |s| {
            product_or_not_found(s, &r.product)?;
            let usage = s.usage.get(&r.product, &r.tenant).map_err(store_err)?;
            Ok(Response::new(pb::ReadUsageResponse {
                usage: usage.map(|u| usage_to_pb(&TenantId(r.tenant.clone()), &u)),
            }))
        })
        .await
    }

    async fn read_all(
        &self,
        req: Request<pb::ReadAllUsageRequest>,
    ) -> Result<Response<pb::ReadAllUsageResponse>, Status> {
        let r = req.into_inner();
        blocking(&self.0, move |s| {
            product_or_not_found(s, &r.product)?;
            let all = s.usage.all(&r.product).map_err(store_err)?;
            Ok(Response::new(pb::ReadAllUsageResponse {
                usages: all.iter().map(|(t, u)| usage_to_pb(t, u)).collect(),
            }))
        })
        .await
    }

    /// The kept series for one tenant, oldest first. See the proto for the
    /// retention window and why a `since` older than it is an answer, not an
    /// error; see [`crate::state::UsageStore`] for what prunes it.
    async fn history(
        &self,
        req: Request<pb::UsageHistoryRequest>,
    ) -> Result<Response<pb::UsageHistoryResponse>, Status> {
        let r = req.into_inner();
        blocking(&self.0, move |s| {
            product_or_not_found(s, &r.product)?;
            if r.tenant.is_empty() {
                return Err(Status::invalid_argument(
                    "history is per tenant: tenant is required",
                ));
            }
            let tenant = TenantId(r.tenant.clone());
            let readings = s
                .usage
                .history(&r.product, &r.tenant, r.since_unix_ms, r.limit as usize)
                .map_err(store_err)?;
            let kept = s.usage.kept(&r.product, &r.tenant).map_err(store_err)?;
            Ok(Response::new(pb::UsageHistoryResponse {
                readings: readings.iter().map(|u| usage_to_pb(&tenant, u)).collect(),
                kept,
            }))
        })
        .await
    }

    /// **The rate.** `monetize::trend` over the readings this server already
    /// holds — a fold, not a measurement (`BASE-MODEL.md` rule 5: the product
    /// counts, monetize decides).
    ///
    /// An empty `tenant` is the FLEET: every tenant's rate, added. A tenant whose
    /// own series cannot support one is counted, never folded in as zero, so the
    /// caller can tell a fleet figure that is a total from one that is a floor.
    async fn trend(
        &self,
        req: Request<pb::TrendRequest>,
    ) -> Result<Response<pb::TrendResponse>, Status> {
        let r = req.into_inner();
        blocking(&self.0, move |s| {
            product_or_not_found(s, &r.product)?;
            if r.meter.is_empty() {
                return Err(Status::invalid_argument(
                    "a rate is per meter: name one of the product's meters (Products.List). There is no default \
                     meter, because a rate quoted for a meter the caller did not name is a number nobody can check",
                ));
            }
            let (since, window_ms) = window(s, r.window_ms);

            if !r.tenant.is_empty() {
                let readings = s.usage.history(&r.product, &r.tenant, since, TREND_READINGS).map_err(store_err)?;
                let t = monetize::trend::rate_of(&readings, &r.meter);
                let measured = u64::from(matches!(t, Trend::Rate(_)));
                return Ok(Response::new(trend_to_pb(t, window_ms, measured, 1 - measured)));
            }

            // The fleet. Every tenant the store knows of for this product — the
            // same list `ReadAll` answers from, so the fleet a rate is quoted for
            // is the fleet the console lists.
            let mut rates = Vec::new();
            let mut unmeasured = 0u64;
            for (tenant, _) in s.usage.all(&r.product).map_err(store_err)? {
                let readings = s.usage.history(&r.product, &tenant.0, since, TREND_READINGS).map_err(store_err)?;
                match monetize::trend::rate_of(&readings, &r.meter) {
                    Trend::Rate(rate) => rates.push(rate),
                    // NOT a zero. A tenant monetize cannot measure the slope of
                    // is a hole in the fleet figure, and the count is how the
                    // console learns the figure is a floor.
                    Trend::NotEnoughHistory(_) => unmeasured += 1,
                }
            }
            let measured = rates.len() as u64;
            let t = match monetize::Rate::sum(&rates) {
                Some(rate) => Trend::Rate(rate),
                // Not one tenant could be measured: unknown, not a fleet at rest.
                None => Trend::NotEnoughHistory(monetize::trend::NotEnoughHistory {
                    readings: 0,
                    span_ms: 0,
                    needed_span_ms: trend::MIN_SPAN_MS,
                }),
            };
            Ok(Response::new(trend_to_pb(t, window_ms, measured, unmeasured)))
        })
        .await
    }

    /// **The fleet total and the oversell number.** `monetize::fleet` over the
    /// stored readings, the stored facts, and the poller's CACHED capacity
    /// answer.
    ///
    /// The cache is the load-bearing choice: `Product::servable` is a call to the
    /// product's control plane, and making it here would hang a Products page on
    /// the slowest box in the estate — which is exactly what `UI.md`'s
    /// reachability dot exists to avoid. See `crate::health`.
    /// **The tenant's flow series, asked of the PRODUCT.**
    ///
    /// A passthrough and not a fold, unlike [`Self::history`] and
    /// [`Self::trend`] beside it. The product is the only side that counts flow
    /// (`BASE-MODEL.md` rule 5: the product counts, monetize decides), and a
    /// copy kept in the usage store would be a second series to go stale — so
    /// this asks, every time, and FAILS when the product cannot answer.
    ///
    /// Failing is the whole point of not defaulting to an empty series. The
    /// console draws an empty series as *this customer has gone quiet*, and a
    /// product that is merely unreachable must never be able to put a working
    /// customer on the SILENT list. `monetize_product::Product::read_activity`'s
    /// default refuses by name for the same reason.
    ///
    /// It runs on the blocking pool like every other plugin call, and is bounded
    /// by the plugin's own per-call deadline.
    async fn activity(
        &self,
        req: Request<pb::ActivityRequest>,
    ) -> Result<Response<pb::ActivityResponse>, Status> {
        let r = req.into_inner();
        blocking(&self.0, move |s| {
            let product = product_or_not_found(s, &r.product)?;
            if r.tenant.is_empty() {
                return Err(Status::invalid_argument(
                    "activity is per tenant: tenant is required. There is no fleet answer,                      because two tenants' pushes are not one tenant's habits",
                ));
            }
            let activity = product
                .read_activity(&TenantId(r.tenant.clone()), r.since_unix_ms, r.until_unix_ms)
                .map_err(super::product_err)?;
            Ok(Response::new(pb::ActivityResponse {
                days: activity.days.iter().map(activity_day_to_pb).collect(),
                retained_days: activity.retained_days,
            }))
        })
        .await
    }

    async fn fleet(
        &self,
        req: Request<pb::FleetRequest>,
    ) -> Result<Response<pb::FleetResponse>, Status> {
        let r = req.into_inner();
        blocking(&self.0, move |s| {
            let product = product_or_not_found(s, &r.product)?;
            let usages = s.usage.all(&r.product).map_err(store_err)?;
            let facts = s
                .ledger
                .entitlements(&r.product)
                .map_err(super::ledger_err)?;
            let facts = crate::signup::with_signup_facts(s, &r.product, facts)
                .map_err(|e| Status::internal(format!("signup store: {e}")))?;
            let health = s.health.get(&r.product);
            let servable = health.servable_or_unasked();

            // Only the per-TENANT meters. A Scope::Product meter is not in the
            // list at all — `monetize::fleet::totals` drops it, because there is
            // nothing to add up.
            let meters = monetize::fleet::totals(product.meters(), &usages, &facts, &servable)
                .iter()
                .map(fleet_meter_to_pb)
                .collect();

            let (
                servable_measured,
                servable_bytes,
                total_bytes,
                servable_reason,
                growth,
                growth_detail,
            ) = match &servable {
                Servable::Measured {
                    servable_bytes,
                    total_bytes,
                    growth,
                    ..
                } => (
                    true,
                    *servable_bytes,
                    *total_bytes,
                    String::new(),
                    growth.name().to_owned(),
                    growth.detail().to_owned(),
                ),
                // An unmeasured box has not said whether it can grow either:
                // empty, not `unknown`, so a reader cannot mistake "nobody asked"
                // for "it answered that it could not tell".
                Servable::Unmeasured(why) => {
                    (false, 0, 0, why.clone(), String::new(), String::new())
                }
            };
            Ok(Response::new(pb::FleetResponse {
                meters,
                servable_measured,
                servable_bytes,
                total_bytes,
                servable_reason,
                servable_at_unix_ms: health.servable_at_unix_ms,
                growth,
                growth_detail,
                cloud: Some({
                    let mut c = cloud_inventory_pb(
                        &r.product,
                        s.registry.cloud_for_transactions(),
                        &s.ledger,
                        &EstateIron::of(s),
                    );
                    // MAP-3: the slot it was listed through names the account; every product's
                    // block from one slot is one account.
                    c.account = s
                        .registry
                        .transaction_slot()
                        .map(|h| h.name().to_owned())
                        .unwrap_or_default();
                    c
                }),
            }))
        })
        .await
    }
}

/// **One estate order's laid iron**, as the CLOUD panel counts it OWNED (2026-10-22):
/// an estate order keeps what it bought in its `laid` record, never as ledger
/// holdings, so a panel reading the ledger alone called every shop-laid machine
/// an orphan. A run that is gone ([`phase::is_gone`]) or never laid owns nothing.
#[derive(Clone, Debug, PartialEq)]
pub struct LaidIron {
    /// `estate/<company>` — the label every laid resource carries.
    pub reference: String,
    pub laid: LaidEstate,
    /// The provider ids the give-back already asked to go: absent, never missing.
    pub given_back: Vec<String>,
    /// **The estate this iron belongs to** (MAP-SEG 1, 2026-10-26): the run's fleet name —
    /// a site's label (`test2-gunnar-rs`), a sold estate's company — the name the console's
    /// `/e/<estate>/` pages are addressed by. Empty: not known (a bare record).
    pub estate: String,
    /// **Adopted, not laid** (MAP-SEG 4): a kit-installed site the ONE box adopted
    /// ([`EstateRun::adopted_at_ms`]). Its machines carry no label of this box (the kit made
    /// them), so the provider's labelled listing never holds them; the inventory looks each
    /// one up by the uuid the adoption read back ([`adopted_standing`]).
    pub adopted: bool,
}

impl LaidIron {
    pub fn of(run: &EstateRun) -> Option<Self> {
        Self::from_parts(
            &run.phase,
            &run.reference,
            run.laid.as_ref(),
            &run.given_back,
        )
        .map(|l| l.named(run.fleet_name()).adopted_if(run.adopted_at_ms > 0))
    }

    pub fn from_parts(
        phase_now: &str,
        reference: &str,
        laid: Option<&LaidEstate>,
        given_back: &[String],
    ) -> Option<Self> {
        if phase::is_gone(phase_now) {
            return None;
        }
        Some(LaidIron {
            reference: reference.to_owned(),
            laid: laid?.clone(),
            given_back: given_back.to_vec(),
            estate: String::new(),
            adopted: false,
        })
    }

    /// The estate (its fleet name) this iron belongs to.
    pub fn named(mut self, estate: &str) -> Self {
        self.estate = estate.to_owned();
        self
    }

    /// Marked adopted (kit-installed, not laid by this box) when `adopted`.
    pub fn adopted_if(mut self, adopted: bool) -> Self {
        self.adopted = adopted;
        self
    }
}

/// **Which estate a cloud row belongs to** (MAP-SEG 1, 2026-10-26: the Map of ONE estate
/// listed the iron of every estate on the account). By the row's reference: an estate
/// order's `estate/<company>` is that run's estate ([`LaidIron::estate`]; a run gone or
/// unknown here: its company, which is a sold estate's fleet name); a tenant's holding
/// `<product>/@<estate>/<ns>/…` is the sold estate `<estate>`. Anything else (a product's
/// own tenant, the box's own data set, an unlabelled row) is `""`: no ONE estate's, so it
/// shows on the operator's account-wide Iron page and on no estate's Map.
pub fn estate_of(reference: &str, estates: &[LaidIron]) -> String {
    if reference.is_empty() {
        return String::new();
    }
    if let Some(l) = estates.iter().find(|l| l.reference == reference) {
        if !l.estate.is_empty() {
            return l.estate.clone();
        }
    }
    if let Some(company) = reference.strip_prefix("estate/") {
        return company.split('/').next().unwrap_or("").to_owned();
    }
    reference
        .split('/')
        .nth(1)
        .and_then(|t| t.strip_prefix('@'))
        .map(|e| e.split('/').next().unwrap_or("").to_owned())
        .unwrap_or_default()
}

/// **The estate orders' iron, for [`cloud_inventory_pb`]**: every laid, not-gone run,
/// and the product estates are sold as (`[estate_orders] product`) — the panel that
/// lists them as its own. `product: None` (nothing sold here) still passes the laid
/// rows, so no other product's panel calls them orphans.
#[derive(Clone, Debug, Default, PartialEq)]
pub struct EstateIron {
    pub product: Option<String>,
    pub laid: Vec<LaidIron>,
}

impl EstateIron {
    pub fn of(state: &AppState) -> Self {
        EstateIron {
            product: state.sold_product().ok().map(str::to_owned),
            laid: state
                .estates
                .all()
                .iter()
                .filter_map(LaidIron::of)
                .collect(),
        }
    }
}

/// **The laid records as ledger-shaped rows**, so the pure [`monetize::reconcile`]
/// can match them: each laid machine's server and every disk, under the run's
/// reference, with the id the provider LISTS it by (a laid id is bare, a listed one
/// may carry a kind prefix — [`same_resource`]). A laid id the provider no longer
/// lists keeps its bare form and comes out MISSING, unless the give-back already
/// asked it to go. A release clone counts only while it is listed: it is ejected
/// after hand-over, and its absence is no loss.
pub fn estate_holdings(provider: &str, listed: &[Owned], estates: &[LaidIron]) -> Vec<Holding> {
    use monetize_cloud::{Resource, ResourceId, ServerId, ServerRole};
    let mut out: Vec<Holding> = Vec::new();
    for e in estates {
        let given_back = |laid: &str| e.given_back.iter().any(|g| same_resource(g, laid));
        let mut push = |laid: &str, resource: Resource, only_listed: bool| {
            if laid.trim().is_empty() {
                return;
            }
            let id = match listed
                .iter()
                .find(|o| o.id.provider == provider && same_resource(&o.id.id, laid))
            {
                Some(o) => o.id.clone(),
                None if only_listed || given_back(laid) => return,
                None => ResourceId {
                    provider: provider.to_owned(),
                    id: laid.to_owned(),
                },
            };
            if out.iter().any(|h| h.id.as_ref() == Some(&id)) {
                return;
            }
            out.push(Holding {
                reference: e.reference.clone(),
                resource,
                id: Some(id),
            });
        };
        // An adopted site's machines are compared like any laid ones (MAP-SEG 4): the
        // inventory looked each up BY ITS UUID first ([`adopted_standing`]), so a machine that
        // stands is listed and one really gone is MISSING.
        let only_listed = false;
        for m in &e.laid.machines {
            let role = if m.role == "twin" {
                ServerRole::Replica
            } else {
                ServerRole::Primary
            };
            push(
                &m.server,
                Resource::Server {
                    plan: m.plan.clone(),
                    zone: e.laid.zone.clone(),
                    role,
                },
                only_listed,
            );
            for d in &m.disks {
                push(
                    &d.id,
                    Resource::Disk {
                        server: ServerId(m.server.clone()),
                        gib: d.gib,
                    },
                    only_listed,
                );
            }
            push(
                &m.medium_clone,
                Resource::Disk {
                    server: ServerId(m.server.clone()),
                    gib: 0,
                },
                true,
            );
        }
    }
    out
}

/// **An adopted estate's machines, looked up BY UUID** (MAP-SEG 4, owner 2026-10-26: "3 MISSING
/// gunnarrs servers"). A kit-installed site's servers and disks carry no `monetize_ref` label, so
/// the labelled listing never holds them and every one read MISSING. Each one the listing does
/// not hold is asked for by the uuid its adoption read back (`Listing::Status`): one that
/// stands is a listed row under the run's reference (unpriced: nothing listed its price); one
/// the provider no longer has is not added, so it is MISSING; one the provider could not say
/// about is left out of the comparison ([`LaidIron`] cut), never called missing on a guess.
pub fn adopted_standing(
    cloud: &dyn Cloud,
    listed: &[Owned],
    estates: &[LaidIron],
    currency: monetize_pay::Currency,
) -> (Vec<Owned>, Vec<LaidIron>) {
    use monetize_cloud::{CloudError, OwnedKind, ResourceId, ResourceStatus};
    let named = cloud.manifest().provider;
    let provider = named.as_str();
    let mut found = Vec::new();
    let mut cut = Vec::new();
    for e in estates {
        if !e.adopted {
            cut.push(e.clone());
            continue;
        }
        let mut e = e.clone();
        let zone = e.laid.zone.0.clone();
        let mut unknown: Vec<String> = Vec::new();
        let mut ask = |bare: &str,
                       kind: OwnedKind,
                       gib: u64,
                       attached_to: Option<String>,
                       found: &mut Vec<Owned>| {
            if bare.trim().is_empty()
                || listed
                    .iter()
                    .any(|o| o.id.provider == provider && same_resource(&o.id.id, bare))
            {
                return;
            }
            let prefix = if kind == OwnedKind::Server {
                "server"
            } else {
                "storage"
            };
            let id = ResourceId {
                provider: provider.to_owned(),
                id: if bare.contains('/') {
                    bare.to_owned()
                } else {
                    format!("{prefix}/{bare}")
                },
            };
            match monetize_cloud::ask::status(&cloud, &id) {
                Ok(ResourceStatus::Gone) | Err(CloudError::UnknownResource(_)) => {}
                Ok(_) => found.push(Owned {
                    id,
                    kind,
                    gib,
                    zone: zone.clone(),
                    attached_to,
                    reference: Some(e.reference.clone()),
                    monthly_minor: None,
                    currency,
                    provenance: provider.to_owned(),
                    resource: None,
                    backup: None,
                }),
                Err(err) => {
                    eprintln!("monetize-server: the adopted {} {bare} could not be looked up ({err}): it is left out of the iron's comparison", e.reference);
                    unknown.push(bare.to_owned());
                }
            }
        };
        for m in &e.laid.machines {
            ask(&m.server, OwnedKind::Server, 0, None, &mut found);
            for d in &m.disks {
                ask(
                    &d.id,
                    OwnedKind::Disk,
                    d.gib,
                    Some(m.server.clone()),
                    &mut found,
                );
            }
        }
        for m in &mut e.laid.machines {
            m.disks.retain(|d| !unknown.contains(&d.id));
        }
        e.laid.machines.retain(|m| !unknown.contains(&m.server));
        cut.push(e);
    }
    (found, cut)
}

/// **CLOUD: what we own, what it costs, orphans/missing** — for one product.
///
/// The provider is LISTED here, live, then reconciled against the WHOLE ledger
/// (`all_holdings`, not this product's slice): an orphan is a resource in no
/// product's ledger, and only the whole ledger can say that. The result is then
/// cut to `product`: its matched holdings and its missing ones — plus every
/// orphan, on every product, because an orphan belongs to none and must be seen.
///
/// The estate orders' laid iron ([`EstateIron`]) is reconciled with the ledger: a
/// shop-laid machine is OWNED under `estate/<company>` on the sold product's panel,
/// never an orphan. Nothing here cleans anything up: the list is for eyes.
///
/// A provider that cannot be listed answers `available: false` with the reason
/// and empty lists; the fleet's meters still render. Nobody asked is not
/// "nothing is there".
pub fn cloud_inventory_pb(
    product: &str,
    cloud: &dyn Cloud,
    ledger: &monetize::Ledger,
    estates: &EstateIron,
) -> pb::CloudInventory {
    let provider = cloud.manifest().provider.to_owned();
    let unavailable = |error: String| pb::CloudInventory {
        provider: provider.clone(),
        available: false,
        error,
        ..Default::default()
    };
    let inv = match monetize_cloud::ask::account(&cloud) {
        Ok(i) => i,
        Err(e) => return unavailable(e.to_string()),
    };
    let mut all = match ledger.all_holdings() {
        Ok(h) => h,
        Err(e) => return unavailable(format!("ledger: {e}")),
    };
    let mut inv = inv;
    let (standing, laid) = adopted_standing(cloud, &inv.owned, &estates.laid, inv.currency);
    inv.owned.extend(standing);
    // MAP-3: a backup is no order's disk; it is classified by its origin below.
    let (backup_rows, rows): (Vec<Owned>, Vec<Owned>) = std::mem::take(&mut inv.owned)
        .into_iter()
        .partition(Owned::is_backup);
    inv.owned = rows;
    all.extend(estate_holdings(&provider, &inv.owned, &laid));
    let rec = monetize::reconcile(&inv.owned, &all);
    let prefix = format!("{product}/");
    // The sold product's panel lists the estates it laid as its own.
    let sells_estates = estates.product.as_deref() == Some(product);
    let mine = |reference: &str| {
        reference.starts_with(&prefix)
            || (sells_estates && estates.laid.iter().any(|l| l.reference == reference))
    };
    // What this product's orders bought, then the box's own iron — the `server`
    // cloud's `dataset` row for THIS product, which no order bought and which
    // the panel shows as the iron itself rather than as an orphan.
    let owned: Vec<pb::OwnedResource> = rec
        .matched
        .iter()
        .filter(|m| mine(&m.holding.reference))
        .map(|m| {
            owned_to_pb(
                &m.owned,
                &m.holding.reference,
                &estate_of(&m.holding.reference, &estates.laid),
            )
        })
        .chain(
            rec.own
                .iter()
                .filter(|o| o.attached_to.as_deref() == Some(product))
                .map(|o| owned_to_pb(o, "", "")),
        )
        .collect();
    let mut orphans: Vec<pb::OwnedResource> = rec
        .orphans
        .iter()
        .map(|o| {
            let reference = o.reference.as_deref().unwrap_or("");
            owned_to_pb(o, reference, &estate_of(reference, &estates.laid))
        })
        .collect();
    let (backups, orphan_backups) = backups_of(&backup_rows, &rec, &estates.laid);
    orphans.extend(orphan_backups);
    let missing = rec
        .missing
        .iter()
        .filter(|h| mine(&h.reference))
        // `missing` only ever holds BOUGHT holdings (`reconcile` drops OnHand), so
        // the id is always there; `filter_map` says so without an unwrap.
        .filter_map(|h| {
            let id = h.id.clone()?;
            Some(pb::MissingResource {
                provider: id.provider,
                id: id.id,
                reference: h.reference.clone(),
                tenant: tenant_of(&h.reference),
                resource: monetize_cloud::fingerprint(&h.resource),
                estate: estate_of(&h.reference, &estates.laid),
            })
        })
        .collect();
    pb::CloudInventory {
        provider,
        available: true,
        error: String::new(),
        total_bytes: owned.iter().map(|o| o.gib << 30).sum(),
        monthly_minor: owned
            .iter()
            .filter(|o| o.priced)
            .map(|o| o.monthly_minor)
            .sum(),
        unpriced: owned.iter().filter(|o| !o.priced).count() as u64,
        owned,
        orphans,
        missing,
        foreign_count: inv.foreign,
        // The provider's own word on what `monthly_minor` is a number of,
        // spelled as `currency_name` spells `Money` to the console.
        currency: inv.currency.code().to_owned(),
        backup_bytes: backups.iter().map(|b| b.gib << 30).sum(),
        backups,
        // The linked cloud's name, set by the caller that knows the slot ([`Usage::fleet`]).
        account: String::new(),
    }
}

/// The two spellings of one storage (`storage/<uuid>` listed, `<uuid>` laid) are the same.
fn same_storage(a: &str, b: &str) -> bool {
    same_resource(a, b) || same_resource(b, a)
}

/// **The account's backups, each by the disk it was taken of** (MAP-3, owner 2026-10-27):
/// a backup of a disk an order or an estate holds (`rec.matched`) is that estate's; a backup
/// of a disk that stands and is no order's (the ONE box's own disk) is the account's own, no
/// estate's; a backup whose disk is GONE, or is itself an orphan, is an orphan, by its title.
/// Answers (the backups, the orphan backups).
fn backups_of(
    rows: &[Owned],
    rec: &monetize::Reconciliation,
    laid: &[LaidIron],
) -> (Vec<pb::BackupResource>, Vec<pb::OwnedResource>) {
    let mut backups = Vec::new();
    let mut orphans = Vec::new();
    for b in rows {
        let Some(of) = b.backup.as_ref() else {
            continue;
        };
        let own_reference = b.reference.as_deref().unwrap_or("");
        let disk_is_orphan = rec
            .orphans
            .iter()
            .any(|o| same_storage(&o.id.id, &of.origin));
        if !of.origin_standing || of.origin.is_empty() || disk_is_orphan {
            orphans.push(owned_to_pb(
                b,
                own_reference,
                &estate_of(own_reference, laid),
            ));
            continue;
        }
        // The disk's holder, or none: a disk that stands and no order labelled.
        let holder = rec
            .matched
            .iter()
            .find(|m| same_storage(&m.owned.id.id, &of.origin))
            .map(|m| m.holding.reference.as_str());
        let estate = holder.map(|r| estate_of(r, laid)).unwrap_or_default();
        let of_what = if !of.server.is_empty() {
            of.server.as_str()
        } else {
            of.origin.as_str()
        };
        let day = of.created.get(..10).unwrap_or(of.created.as_str());
        backups.push(pb::BackupResource {
            provider: b.id.provider.clone(),
            id: b.id.id.clone(),
            gib: b.gib,
            zone: b.zone.clone(),
            origin: of.origin.clone(),
            server: of.server.clone(),
            created: of.created.clone(),
            title: of.title.clone(),
            estate,
            reference: holder.unwrap_or(own_reference).to_owned(),
            words: if day.is_empty() {
                format!("backup of {of_what}")
            } else {
                format!("backup of {of_what}, {day}")
            },
        });
    }
    (backups, orphans)
}

/// The tenant is the reference's second segment (`<product>/<tenant>/<date>…`).
fn tenant_of(reference: &str) -> String {
    reference.split('/').nth(1).unwrap_or("").to_owned()
}

fn owned_to_pb(o: &monetize_cloud::Owned, reference: &str, estate: &str) -> pb::OwnedResource {
    pb::OwnedResource {
        provider: o.id.provider.clone(),
        id: o.id.id.clone(),
        kind: if o.is_backup() {
            "backup".to_owned()
        } else {
            o.kind.name().to_owned()
        },
        gib: o.gib,
        zone: o.zone.clone(),
        attached_to: o.attached_to.clone().unwrap_or_default(),
        reference: reference.to_owned(),
        tenant: tenant_of(reference),
        priced: o.monthly_minor.is_some(),
        monthly_minor: o.monthly_minor.unwrap_or(0),
        provenance: o.provenance.clone(),
        estate: estate.to_owned(),
        resource: o.resource.clone().unwrap_or_default(),
        title: o
            .backup
            .as_ref()
            .map(|b| b.title.clone())
            .unwrap_or_default(),
    }
}

/// One fleet total on the wire. The `oversell` STRING is read before
/// `oversell_bytes`, because `unmeasured` and `not_storage` carry no bytes and a
/// reader that took the number alone would see a confident zero.
fn fleet_meter_to_pb(t: &monetize::FleetTotal) -> pb::FleetMeter {
    let (oversell, oversell_bytes, oversell_reason) = match t.oversell() {
        Oversell::Oversold { by } => ("oversold", by, String::new()),
        Oversell::Fits { headroom } => ("fits", headroom, String::new()),
        Oversell::Unmeasured(why) => ("unmeasured", 0, why),
        Oversell::NotStorage => ("not_storage", 0, String::new()),
    };
    pb::FleetMeter {
        meter: t.meter.clone(),
        tenants: t.tenants as u64,
        used: t.used,
        tenants_without_reading: t.tenants_without_reading as u64,
        allowance: t.allowance,
        tenants_without_cap: t.tenants_without_cap as u64,
        oversell: oversell.into(),
        oversell_bytes,
        oversell_reason,
        capacity: t.capacity(),
        is_a_floor: t.is_a_floor(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::BTreeMap;

    use monetize_proto::usage_server::Usage as _;

    use monetize::testing::MockProduct;
    use monetize_product::Usage;

    use crate::registry::Registry;

    const GIB: u64 = 1 << 30;
    const DAY: u64 = 24 * 60 * 60 * 1000;
    const NOW: u64 = 1_788_523_200_000;

    fn state() -> Arc<AppState> {
        let mut s = AppState::in_memory(Registry::new().product(MockProduct::gunnar()));
        // A fixed clock, so the 30-day window lands on the readings the test wrote
        // rather than on wherever today happens to be.
        s.clock = Box::new(|| NOW);
        Arc::new(s)
    }

    fn store(s: &AppState, tenant: &str, days: u64, mut value: impl FnMut(u64) -> u64) {
        for d in 0..days {
            let meters: BTreeMap<String, u64> = [("pack_bytes".to_string(), value(d))].into();
            s.usage
                .put(
                    "gunnar",
                    tenant,
                    &Usage {
                        meters,
                        measured_at_unix_ms: NOW - (days - 1 - d) * DAY,
                    },
                )
                .unwrap();
        }
    }

    async fn ask(s: &Arc<AppState>, tenant: &str, meter: &str) -> pb::TrendResponse {
        UsageService(s.clone())
            .trend(Request::new(pb::TrendRequest {
                product: "gunnar".into(),
                tenant: tenant.into(),
                meter: meter.into(),
                window_ms: 0,
            }))
            .await
            .expect("the product is linked and the meter is named")
            .into_inner()
    }

    /// (r) **The RPC carries the three answers apart**: a measured tenant gets a
    /// value, a tenant with an hour of history gets `enough_history = false`, and
    /// a flat tenant gets a rate of ZERO with `enough_history = true`.
    ///
    /// Asserted on the wire fields, because the whole risk of this endpoint is a
    /// serialisation that flattens "unknown" and "zero" into the same `0.0`.
    #[tokio::test]
    async fn the_wire_keeps_unknown_and_zero_apart() {
        let s = state();
        store(&s, "growing", 28, |d| 10 * GIB + d * GIB / 7); // 1 GiB/wk
        store(&s, "flat", 28, |_| 5 * GIB);
        s.usage
            .put(
                "gunnar",
                "fresh",
                &Usage {
                    meters: [("pack_bytes".to_string(), GIB)].into(),
                    measured_at_unix_ms: NOW - 3_600_000,
                },
            )
            .unwrap();
        s.usage
            .put(
                "gunnar",
                "fresh",
                &Usage {
                    meters: [("pack_bytes".to_string(), 3 * GIB)].into(),
                    measured_at_unix_ms: NOW,
                },
            )
            .unwrap();

        let growing = ask(&s, "growing", "pack_bytes").await;
        assert!(growing.enough_history);
        assert!(
            (growing.per_week / GIB as f64 - 1.0).abs() < 0.01,
            "{} bytes/wk",
            growing.per_week
        );
        assert_eq!(growing.confidence, "firm");
        assert_eq!(
            growing.window_ms, DEFAULT_WINDOW_MS,
            "the window is echoed so the console can print 'last 30 d'"
        );

        let flat = ask(&s, "flat", "pack_bytes").await;
        assert!(flat.enough_history, "a month of stillness IS history");
        assert_eq!(flat.per_week, 0.0);

        let fresh = ask(&s, "fresh", "pack_bytes").await;
        assert!(!fresh.enough_history, "an hour apart is not a week");
        assert_eq!(
            fresh.per_week, 0.0,
            "the field is empty, and `enough_history` is what says so"
        );
        assert_eq!(fresh.needed_span_ms, monetize::trend::MIN_SPAN_MS);
        assert_eq!(fresh.span_ms, 3_600_000);
    }

    /// (r) **The fleet arm counts the tenants it could not measure and does not
    /// fold them in as zero.** A fleet total that quietly treats an unmeasurable
    /// tenant as flat is the arithmetic-on-nothing bug, and the count is the only
    /// thing that lets a console say the figure is a floor.
    #[tokio::test]
    async fn the_fleet_arm_counts_what_it_could_not_measure() {
        let s = state();
        store(&s, "a", 28, |d| 10 * GIB + d * GIB / 7);
        store(&s, "b", 28, |d| 10 * GIB + d * GIB / 7);
        // Two tenants the poller has only just met.
        for t in ["c", "d"] {
            s.usage
                .put(
                    "gunnar",
                    t,
                    &Usage {
                        meters: [("pack_bytes".to_string(), GIB)].into(),
                        measured_at_unix_ms: NOW,
                    },
                )
                .unwrap();
        }

        let fleet = ask(&s, "", "pack_bytes").await;
        assert!(fleet.enough_history);
        assert_eq!(fleet.measured_tenants, 2);
        assert_eq!(
            fleet.unmeasured_tenants, 2,
            "the two fresh tenants are a hole, not two zeroes"
        );
        assert!(
            (fleet.per_week / GIB as f64 - 2.0).abs() < 0.02,
            "two tenants at 1 GiB/wk is a fleet at 2 GiB/wk, got {}",
            fleet.per_week / GIB as f64
        );

        // A fleet where NOBODY can be measured is unknown, not a fleet at rest.
        let fresh = state();
        for t in ["c", "d"] {
            fresh
                .usage
                .put(
                    "gunnar",
                    t,
                    &Usage {
                        meters: [("pack_bytes".to_string(), GIB)].into(),
                        measured_at_unix_ms: NOW,
                    },
                )
                .unwrap();
        }
        let none = ask(&fresh, "", "pack_bytes").await;
        assert!(!none.enough_history, "no measurable tenant is UNKNOWN");
        assert_eq!(none.measured_tenants, 0);
        assert_eq!(none.unmeasured_tenants, 2);
    }

    async fn fleet(s: &Arc<AppState>) -> pb::FleetResponse {
        UsageService(s.clone())
            .fleet(Request::new(pb::FleetRequest {
                product: "gunnar".into(),
            }))
            .await
            .expect("gunnar is linked")
            .into_inner()
    }

    /// **The wire carries the currency the provider priced in.** A sandbox
    /// with a declared table in SEK — not the mock's EUR, so a constant would
    /// be caught — and the fleet's cloud block says `SEK`. `2.30` alone is a
    /// number an operator can misread; `2.30 SEK` is not.
    #[cfg(feature = "sandbox")]
    #[tokio::test]
    async fn the_cloud_block_carries_the_currency_the_sandbox_priced_in() {
        use monetize::testing::{purchase, MockPay};
        use monetize_cloud::sandbox::{DeclaredPrices, Sandbox, SandboxConfig};
        use monetize_cloud::{Resource, ServerId};
        let mut cfg = SandboxConfig::new();
        cfg.declared = Some(DeclaredPrices {
            disk_minor_per_gib_month: 23,
            plan_minor_per_month: Default::default(),
            currency: monetize_pay::Currency::Sek,
        });
        let s = Arc::new(AppState::in_memory(
            Registry::new()
                .product(MockProduct::gunnar())
                .cloud(Sandbox::new(cfg).unwrap()),
        ));
        let mut p = purchase("alice");
        p.resources = vec![Resource::Disk {
            server: ServerId("gunnar-se-sto1".into()),
            gib: 10,
        }];
        s.transaction(
            s.registry.find_product("gunnar").unwrap(),
            monetize_pay::Vendor::of(&MockPay::new()),
        )
        .run(&p)
        .unwrap();
        let c = fleet(&s).await.cloud.expect("always present");
        assert!(c.available, "{}", c.error);
        assert_eq!(
            (c.provider.as_str(), c.owned.len(), c.monthly_minor),
            ("sandbox", 1, 230),
            "{c:?}"
        );
        assert_eq!(
            c.currency, "SEK",
            "the declared table's currency — not the mock's EUR, not a default of the server's"
        );
    }

    /// **CLOUD on the fleet: owned, then an orphan, then a missing.** The
    /// provider's `live` map is drifted by hand — inserting makes an orphan,
    /// removing makes a missing — and each drift shows up in exactly one list.
    /// With no provider linked the block says so instead of claiming emptiness.
    #[tokio::test]
    async fn the_fleet_carries_the_cloud_inventory_reconciled_against_the_ledger() {
        use monetize::testing::{purchase, Answer, MockCloud, MockPay};
        use monetize_cloud::{Resource, ServerId};
        let mock = Arc::new(MockCloud::new());
        mock.answer_all(Answer::Provisioned);
        let s = Arc::new(AppState::in_memory(
            Registry::new()
                .product(MockProduct::gunnar())
                .cloud(mock.clone()),
        ));
        let pay = MockPay::new();
        let mut p = purchase("alice");
        p.resources = vec![Resource::Disk {
            server: ServerId("gunnar-se-sto1".into()),
            gib: 10,
        }];
        let reference = s
            .transaction(
                s.registry.find_product("gunnar").unwrap(),
                monetize_pay::Vendor::of(&pay),
            )
            .run(&p)
            .unwrap()
            .reference()
            .to_owned();

        let c = fleet(&s).await.cloud.expect("always present");
        assert!(c.available, "{}", c.error);
        assert_eq!(c.provider, "mockcloud");
        assert_eq!(c.owned.len(), 1, "{c:?}");
        let o = &c.owned[0];
        assert_eq!(
            (
                o.id.as_str(),
                o.kind.as_str(),
                o.gib,
                o.tenant.as_str(),
                o.provenance.as_str()
            ),
            ("res-0", "disk", 10, "alice", "mockcloud")
        );
        assert_eq!(
            o.reference, reference,
            "the ledger's reference, not the label's (a mock has none)"
        );
        assert_eq!(o.attached_to, "gunnar-se-sto1");
        assert!(o.priced && o.monthly_minor == 1_000);
        assert_eq!(
            (c.total_bytes, c.monthly_minor, c.unpriced, c.foreign_count),
            (10 << 30, 1_000, 0, 0)
        );
        assert_eq!(
            c.currency, "EUR",
            "the mock prices in EUR and the wire says so"
        );
        assert_eq!(
            c.account, "mockcloud",
            "the linked cloud's slot names the account (MAP-3)"
        );
        assert!(c.orphans.is_empty() && c.missing.is_empty(), "{c:?}");

        // RED: the provider has a disk the ledger never sold.
        mock.live.lock().unwrap().insert(
            "res-forgotten".into(),
            Resource::Disk {
                server: ServerId("gunnar-se-sto1".into()),
                gib: 5,
            },
        );
        let c = fleet(&s).await.cloud.unwrap();
        assert_eq!(
            c.orphans.iter().map(|o| o.id.as_str()).collect::<Vec<_>>(),
            vec!["res-forgotten"]
        );
        assert_eq!(c.owned.len(), 1, "the orphan is not matched to anything");
        assert_eq!(
            c.total_bytes,
            10 << 30,
            "an orphan is not this product's capacity"
        );

        // RED: the ledger says alice holds res-0 and the provider no longer has it.
        mock.live.lock().unwrap().remove("res-0");
        let c = fleet(&s).await.cloud.unwrap();
        assert!(c.owned.is_empty(), "{c:?}");
        let m = &c.missing[0];
        assert_eq!(
            (m.id.as_str(), m.tenant.as_str(), m.resource.as_str()),
            ("res-0", "alice", "disk:gunnar-se-sto1:10")
        );
        assert_eq!(m.reference, reference);
        assert_eq!(c.missing.len(), 1);
        assert_eq!(c.orphans.len(), 1, "the orphan is still there");

        // No provider linked: not an empty inventory, an unavailable one.
        let c = fleet(&state()).await.cloud.unwrap();
        assert!(!c.available);
        assert!(c.error.contains("no cloud provider"), "{}", c.error);
        assert_eq!(c.provider, "none");
    }

    fn meter(f: &pb::FleetResponse, name: &str) -> pb::FleetMeter {
        f.meters
            .iter()
            .find(|m| m.meter == name)
            .unwrap_or_else(|| {
                panic!(
                    "{name} must have a fleet total: {:?}",
                    f.meters.iter().map(|m| &m.meter).collect::<Vec<_>>()
                )
            })
            .clone()
    }

    /// (r) **The oversell number on the wire, and the per-product meter that is
    /// NOT on it.**
    ///
    /// Ten tenants sold 10 GiB each on a box with 55 GiB servable. And
    /// `cpu_millicores` — which every one of them has a cap on — appears in no
    /// entry at all, because nobody measured a tenant's cores.
    #[tokio::test]
    async fn the_fleet_carries_the_oversell_and_leaves_per_product_meters_out() {
        let s = state();
        for i in 0..10 {
            let tenant = format!("t{i}");
            store(&s, &tenant, 1, |_| GIB);
            let fact = monetize_product::EntitlementFact {
                tenant: monetize_product::TenantId(tenant.clone()),
                plan: "10gb-se".into(),
                state: monetize_product::State::Paid,
                paid_until_unix_ms: Some(NOW + DAY),
                caps: [
                    ("pack_bytes".to_string(), 10 * GIB),
                    ("cpu_millicores".to_string(), 2000),
                ]
                .into(),
                source: "operator".into(),
                signature: vec![],
                issued_unix_ms: None,
                issued_signature: vec![],
            };
            s.ledger
                .set_entitlement("gunnar", &s.signer_for("gunnar").sign_fact(fact))
                .unwrap();
        }
        s.health.set_servable(
            "gunnar",
            measured(
                55 * GIB,
                75 * GIB,
                monetize_product::Growth::Unknown("not asked".into()),
            ),
            NOW,
        );

        let f = fleet(&s).await;
        assert!(f.servable_measured);
        assert_eq!(
            (f.servable_bytes, f.total_bytes, f.servable_at_unix_ms),
            (55 * GIB, 75 * GIB, NOW)
        );

        let pack = meter(&f, "pack_bytes");
        assert_eq!(
            (pack.tenants, pack.used, pack.allowance),
            (10, 10 * GIB, 100 * GIB)
        );
        assert_eq!(pack.oversell, "oversold");
        assert_eq!(
            pack.oversell_bytes,
            35 * GIB,
            "100 GiB promised against 10 held plus 55 servable"
        );
        assert_eq!(pack.capacity, Some(65 * GIB));
        assert!(!pack.is_a_floor);

        // THE PER-PRODUCT METER IS ABSENT, by name. Every tenant carries a
        // `cpu_millicores` cap, so a fold that ignored scope would happily
        // report 20 000 millicores of fleet CPU — a number nobody measured.
        assert!(
            !f.meters
                .iter()
                .any(|m| m.meter == "cpu_millicores" || m.meter == "ram_bytes"),
            "a per-product meter must not appear in a per-tenant sum: {:?}",
            f.meters.iter().map(|m| &m.meter).collect::<Vec<_>>()
        );
        assert!(
            f.meters.iter().any(|m| m.meter == "pack_bytes"),
            "the assertion above must not be vacuous"
        );
    }

    /// (r) **A product the poller has not asked yet reports UNMEASURED, not a
    /// fleet that fits comfortably in zero bytes.** The state a freshly started
    /// server is in, and the state the live gunnar.rs appliance is in
    /// permanently until it is upgraded past the `Admin.Capacity` RPC.
    #[tokio::test]
    async fn an_unasked_product_reports_unmeasured_and_not_a_verdict() {
        let s = state();
        store(&s, "a", 1, |_| 4 * GIB);
        let fact = monetize_product::EntitlementFact {
            tenant: monetize_product::TenantId("a".into()),
            plan: "10gb-se".into(),
            state: monetize_product::State::Paid,
            paid_until_unix_ms: Some(NOW + DAY),
            caps: [("pack_bytes".to_string(), 10 * GIB)].into(),
            source: "operator".into(),
            signature: vec![],
            issued_unix_ms: None,
            issued_signature: vec![],
        };
        s.ledger
            .set_entitlement("gunnar", &s.signer_for("gunnar").sign_fact(fact))
            .unwrap();

        // Nothing has been recorded: the poller has not run.
        let f = fleet(&s).await;
        assert!(!f.servable_measured);
        assert_eq!(f.servable_at_unix_ms, 0, "never asked");
        assert!(
            f.servable_reason.contains("has not yet asked"),
            "{}",
            f.servable_reason
        );
        let pack = meter(&f, "pack_bytes");
        assert_eq!(
            (pack.used, pack.allowance),
            (4 * GIB, 10 * GIB),
            "the halves monetize CAN fold are still folded"
        );
        assert_eq!(pack.oversell, "unmeasured", "silence is not a verdict");
        assert_eq!(pack.oversell_bytes, 0);
        assert_eq!(pack.capacity, None, "an unmeasured box has no denominator");
        assert!(pack.is_a_floor);

        // A gunnar that answered "I could not measure" is the same arm with a
        // different reason — and still not a number.
        s.health.set_servable(
            "gunnar",
            monetize_product::Servable::Unmeasured("no Admin.Capacity RPC".into()),
            NOW,
        );
        let f = fleet(&s).await;
        assert!(!f.servable_measured);
        assert_eq!(f.servable_at_unix_ms, NOW, "asked, and it could not say");
        assert_eq!(
            meter(&f, "pack_bytes").oversell_reason,
            "no Admin.Capacity RPC"
        );

        // And the fits-fine arm on the SAME numbers, so neither is unreachable.
        s.health.set_servable(
            "gunnar",
            measured(
                100 * GIB,
                128 * GIB,
                monetize_product::Growth::Unknown("not asked".into()),
            ),
            NOW,
        );
        let pack = meter(&fleet(&s).await, "pack_bytes");
        assert_eq!(pack.oversell, "fits");
        assert_eq!(pack.oversell_bytes, 94 * GIB);
        assert!(!pack.is_a_floor);
    }

    fn measured(
        servable_bytes: u64,
        total_bytes: u64,
        growth: monetize_product::Growth,
    ) -> monetize_product::Servable {
        monetize_product::Servable::Measured {
            servable_bytes,
            total_bytes,
            growth,
            ceilings: Default::default(),
        }
    }

    /// (r) **A SEALED box says so on the wire, with the product's own sentence;
    /// an unmeasured box says nothing about growth at all.**
    ///
    /// RED before `growth` was on `FleetResponse`: the console's `⚠ cannot
    /// grow` had no field to read, and a fleet that was full AND sealed looked
    /// exactly like one that wanted a disk.
    #[tokio::test]
    async fn a_sealed_fleet_carries_the_growth_fact_and_an_unmeasured_one_carries_none() {
        let s = state();
        store(&s, "a", 1, |_| 4 * GIB);

        // Never asked: no growth claim of any kind.
        let f = fleet(&s).await;
        assert!(!f.servable_measured);
        assert_eq!(
            (f.growth.as_str(), f.growth_detail.as_str()),
            ("", ""),
            "an unmeasured box has not said whether it can grow"
        );

        let sentence = "a disk bought and attached to this box would be BILLED AND INVISIBLE. Serving more needs a fresh install";
        s.health.set_servable(
            "gunnar",
            measured(
                55 * GIB,
                75 * GIB,
                monetize_product::Growth::Sealed(sentence.into()),
            ),
            NOW,
        );
        let f = fleet(&s).await;
        assert_eq!(f.growth, "sealed");
        assert_eq!(
            f.growth_detail, sentence,
            "the product's sentence, verbatim"
        );

        // UNKNOWN is its own word, never folded into sealed.
        s.health.set_servable(
            "gunnar",
            measured(
                55 * GIB,
                75 * GIB,
                monetize_product::Growth::Unknown("could not tell".into()),
            ),
            NOW,
        );
        let f = fleet(&s).await;
        assert_eq!(f.growth, "unknown");
        assert_eq!(f.growth_detail, "could not tell");

        s.health.set_servable(
            "gunnar",
            measured(
                55 * GIB,
                75 * GIB,
                monetize_product::Growth::OperatorOnly("extend it by hand".into()),
            ),
            NOW,
        );
        assert_eq!(fleet(&s).await.growth, "operator_only");
    }

    /// (r) A rate with no meter named is refused, not defaulted. A default meter
    /// would quote a number against a meter the caller never asked about.
    #[tokio::test]
    async fn refuse_twin_a_rate_needs_a_meter_and_a_known_product() {
        let s = state();
        let err = UsageService(s.clone())
            .trend(Request::new(pb::TrendRequest {
                product: "gunnar".into(),
                tenant: "a".into(),
                meter: String::new(),
                window_ms: 0,
            }))
            .await
            .expect_err("no meter must refuse");
        assert_eq!(err.code(), tonic::Code::InvalidArgument);
        assert!(err.message().contains("meter"), "{}", err.message());

        let err = UsageService(s)
            .trend(Request::new(pb::TrendRequest {
                product: "idun".into(),
                tenant: String::new(),
                meter: "pack_bytes".into(),
                window_ms: 0,
            }))
            .await
            .expect_err("an unlinked product must refuse");
        assert_eq!(err.code(), tonic::Code::NotFound);
    }

    // ── the estate orders' laid iron on the CLOUD panel (2026-10-22) ──

    /// A provider whose listing is fixed by the test.
    struct Listed(Vec<monetize_cloud::Owned>);

    impl Listed {
        pub fn provider(&self) -> &'static str {
            "upcloud"
        }
        pub fn zones(&self) -> &[monetize_cloud::Zone] {
            &[]
        }
        pub fn price_resource(
            &self,
            _: &monetize_cloud::Resource,
        ) -> Result<monetize_cloud::Price, monetize_cloud::CloudError> {
            Err(monetize_cloud::CloudError::Refused(
                "not in this test".into(),
            ))
        }
        pub fn ensure(
            &self,
            _: &str,
            _: &monetize_cloud::Resource,
        ) -> Result<monetize_cloud::Ensured, monetize_cloud::CloudError> {
            Err(monetize_cloud::CloudError::Refused(
                "nothing is bought in this test".into(),
            ))
        }
        pub fn destroy_id(
            &self,
            _: &monetize_cloud::ResourceId,
        ) -> Result<(), monetize_cloud::CloudError> {
            panic!("the panel never cleans anything up")
        }
        pub fn status(
            &self,
            _: &monetize_cloud::ResourceId,
        ) -> Result<monetize_cloud::ResourceStatus, monetize_cloud::CloudError> {
            Err(monetize_cloud::CloudError::Refused(
                "not in this test".into(),
            ))
        }
        pub fn list_owned(&self) -> Result<monetize_cloud::Inventory, monetize_cloud::CloudError> {
            Ok(monetize_cloud::Inventory {
                owned: self.0.clone(),
                foreign: 0,
                currency: monetize_pay::Currency::Eur,
            })
        }
    }
    impl monetize_cloud::cloud::Cloud for Listed {
        fn manifest(&self) -> monetize_cloud::cloud::CloudManifest {
            monetize_cloud::cloud::CloudManifest {
                provider: self.provider().to_string(),
                zones: self.zones().to_vec(),
                settings: Vec::new(),
                grow_refused: Some(monetize_cloud::grow::unsupported(self.provider()).to_string()),
            }
        }
        fn catalog(
            &self,
            _zone: &monetize_cloud::Zone,
        ) -> Result<monetize_cloud::cloud::Catalog, monetize_cloud::CloudError> {
            Err(monetize_cloud::lay::unsupported(self.provider()))
        }
        fn price(
            &self,
            what: &monetize_cloud::cloud::Priced<'_>,
        ) -> Result<monetize_cloud::Price, monetize_cloud::CloudError> {
            match what {
                monetize_cloud::cloud::Priced::Resource(r) => self.price_resource(r),
                monetize_cloud::cloud::Priced::Plan(p) => {
                    monetize_cloud::price_estate_by_rows(p, |r| self.price_resource(r), None)
                }
                monetize_cloud::cloud::Priced::Grow(_set) => {
                    Err(monetize_cloud::grow::unsupported(self.provider()))
                }
            }
        }
        fn lay(
            &self,
            _plan: &monetize_cloud::lay::EstatePlan,
            _journal: &monetize_cloud::grow::Journal,
        ) -> Result<monetize_cloud::lay::LaidEstate, monetize_cloud::CloudError> {
            Err(monetize_cloud::lay::unsupported(self.provider()))
        }
        fn change(
            &self,
            change: &monetize_cloud::cloud::Change,
            _journal: &monetize_cloud::grow::Journal,
        ) -> Result<monetize_cloud::cloud::Changed, monetize_cloud::CloudError> {
            Ok(match change {
                monetize_cloud::cloud::Change::Plan {
                    server: _,
                    plan: _,
                    delta: _,
                } => {
                    return Err(monetize_cloud::lay::unsupported_verb(
                        self.provider(),
                        "change_plan",
                    ))
                }
                monetize_cloud::cloud::Change::Grow { set: _, estate: _ } => {
                    return Err(monetize_cloud::grow::unsupported(self.provider()))
                }
                monetize_cloud::cloud::Change::Settle { set: _ } => {
                    return Err(monetize_cloud::grow::unsupported(self.provider()))
                }
                monetize_cloud::cloud::Change::ForgetMedia { laid: _ } => {
                    monetize_cloud::cloud::Changed::Forgotten(Vec::new())
                }
                monetize_cloud::cloud::Change::Ensure {
                    reference,
                    resource,
                    room: _,
                } => monetize_cloud::cloud::Changed::Ensured(self.ensure(reference, resource)?),
                monetize_cloud::cloud::Change::Retire { reference, machine } => {
                    monetize_cloud::cloud::Changed::Retired(monetize_cloud::cloud::retire_by_rows(
                        self, reference, machine,
                    )?)
                }
                monetize_cloud::cloud::Change::LabelAdopted { .. } => {
                    return Err(monetize_cloud::lay::unsupported_verb(
                        self.provider(),
                        "label_adopted",
                    ))
                }
            })
        }
        fn boot(
            &self,
            boot: &monetize_cloud::cloud::Boot,
            _journal: &monetize_cloud::grow::Journal,
        ) -> Result<monetize_cloud::cloud::Booted, monetize_cloud::CloudError> {
            match boot {
                monetize_cloud::cloud::Boot::Keep(_k) => Err(
                    monetize_cloud::lay::unsupported_verb(self.provider(), "keep_boot"),
                ),
                monetize_cloud::cloud::Boot::Power { server: _, on: _ } => Err(
                    monetize_cloud::lay::unsupported_verb(self.provider(), "set_power"),
                ),
                monetize_cloud::cloud::Boot::Restore(_r) => Err(
                    monetize_cloud::lay::unsupported_verb(self.provider(), "restore_from_backup"),
                ),
            }
        }
        fn firewall(
            &self,
            _laid: &monetize_cloud::lay::LaidEstate,
        ) -> Result<(), monetize_cloud::CloudError> {
            Err(monetize_cloud::lay::unsupported_verb(
                self.provider(),
                "set_estate_firewall",
            ))
        }
        fn destroy(
            &self,
            what: &monetize_cloud::cloud::Give<'_>,
        ) -> Result<monetize_cloud::Reclaimed, monetize_cloud::CloudError> {
            match what {
                monetize_cloud::cloud::Give::References(refs) => Ok(
                    monetize_cloud::release_for_by_rows(self.list_owned()?, refs, |id| {
                        self.destroy_id(id)
                    }),
                ),
                monetize_cloud::cloud::Give::Resource(id) => {
                    self.destroy_id(id)?;
                    Ok(monetize_cloud::Reclaimed {
                        destroyed: vec![(*id).clone()],
                        ..monetize_cloud::Reclaimed::default()
                    })
                }
            }
        }
        fn inventory(
            &self,
            what: &monetize_cloud::cloud::Listing<'_>,
        ) -> Result<monetize_cloud::cloud::Listed, monetize_cloud::CloudError> {
            Ok(match what {
                monetize_cloud::cloud::Listing::Account => {
                    monetize_cloud::cloud::Listed::Account(self.list_owned()?)
                }
                monetize_cloud::cloud::Listing::Set(_set) => {
                    return Err(monetize_cloud::grow::unsupported(self.provider()))
                }
                monetize_cloud::cloud::Listing::Status(id) => {
                    monetize_cloud::cloud::Listed::Status(self.status(id)?)
                }
                monetize_cloud::cloud::Listing::Under(refs) => {
                    monetize_cloud::cloud::Listed::Under(monetize_cloud::cloud::under(
                        self.list_owned()?,
                        refs,
                    ))
                }
                monetize_cloud::cloud::Listing::Room { delta: _, room: _ } => {
                    monetize_cloud::cloud::Listed::Room(monetize_cloud::cloud::RoomLeft {
                        serve: Ok(()),
                        left_bytes: None,
                        ceilings: Default::default(),
                    })
                }
                monetize_cloud::cloud::Listing::Admits(_plan) => {
                    monetize_cloud::cloud::Listed::Admitted
                }
            })
        }
    }

    fn listed(id: &str, kind: monetize_cloud::OwnedKind, reference: &str) -> monetize_cloud::Owned {
        monetize_cloud::Owned {
            id: monetize_cloud::ResourceId {
                provider: "upcloud".into(),
                id: id.into(),
            },
            kind,
            gib: 20,
            zone: "se-sto1".into(),
            attached_to: None,
            reference: Some(reference.into()),
            monthly_minor: Some(100),
            currency: monetize_pay::Currency::Eur,
            provenance: "upcloud".into(),
            resource: None,
            backup: None,
        }
    }

    /// acme's estate as the shop laid it: front, main, twin, each a server and two disks.
    fn acme_laid() -> LaidEstate {
        use monetize_cloud::lay::{LaidDisk, LaidMachine};
        LaidEstate {
            reference: "estate/acme".into(),
            company: "acme".into(),
            zone: monetize_cloud::Zone("se-sto1".into()),
            machines: ["front", "main", "twin"]
                .iter()
                .map(|role| LaidMachine {
                    role: (*role).into(),
                    hostname: format!("{role}.acme"),
                    title: format!("acme-{role}"),
                    plan: "2xCPU-4GB".into(),
                    server: format!("srv-{role}"),
                    public_ipv4: String::new(),
                    utility_ipv4: String::new(),
                    disks: (0..2)
                        .map(|i| LaidDisk {
                            title: format!("acme-{role}-disk{i}"),
                            id: format!("disk-{role}-{i}"),
                            gib: 20,
                            tier: "maxiops".into(),
                            address: format!("virtio:{i}"),
                        })
                        .collect(),
                    medium_clone: String::new(),
                })
                .collect(),
            narrate_from: String::new(),
            shape: None,
        }
    }

    /// **RED (2026-10-22): a shop-laid estate is OWNED, not orphaned.** The ONE box's
    /// CLOUD panel reconciled the provider against the ledger alone, and an estate
    /// order keeps its iron in its `laid` record — so all nine of acme's resources
    /// read "we pay for this and no order owns it", and the estate's own panel said
    /// "nothing owned". Laid with bare ids, listed with kind prefixes (`server/…`,
    /// `storage/…`) as UpCloud lists them. One laid disk is gone at the provider:
    /// MISSING. One labelled resource no run laid: still an ORPHAN.
    #[test]
    fn an_estate_the_shop_laid_is_owned_under_its_estate_and_never_an_orphan() {
        use monetize_cloud::OwnedKind;
        let s = state();
        let mut at_provider = Vec::new();
        for role in ["front", "main", "twin"] {
            at_provider.push(listed(
                &format!("server/srv-{role}"),
                OwnedKind::Server,
                "estate/acme",
            ));
            for i in 0..2 {
                if (role, i) == ("twin", 1) {
                    continue; // gone at the provider
                }
                at_provider.push(listed(
                    &format!("storage/disk-{role}-{i}"),
                    OwnedKind::Disk,
                    "estate/acme",
                ));
            }
        }
        at_provider.push(listed("storage/stray", OwnedKind::Disk, "estate/ghost"));
        let cloud = Listed(at_provider);
        let estates = EstateIron {
            product: Some("gunnar".into()),
            laid: vec![LaidIron::from_parts(
                phase::CAPTURED,
                "estate/acme",
                Some(&acme_laid()),
                &[],
            )
            .unwrap()],
        };

        let c = cloud_inventory_pb("gunnar", &cloud, &s.ledger, &estates);
        assert!(c.available, "{}", c.error);
        assert_eq!(
            c.orphans.iter().map(|o| o.id.as_str()).collect::<Vec<_>>(),
            vec!["storage/stray"],
            "only the unlaid one is an orphan: {c:?}"
        );
        assert_eq!(c.owned.len(), 8, "3 servers + 5 standing disks: {c:?}");
        assert!(
            c.owned
                .iter()
                .all(|o| o.reference == "estate/acme" && o.tenant == "acme"),
            "{c:?}"
        );
        assert_eq!(c.monthly_minor, 800);
        assert_eq!(
            c.missing
                .iter()
                .map(|m| (m.id.as_str(), m.reference.as_str()))
                .collect::<Vec<_>>(),
            vec![("disk-twin-1", "estate/acme")],
            "{c:?}"
        );

        // Another product's panel does not list acme as its own, nor as orphans.
        let other = cloud_inventory_pb("holger", &cloud, &s.ledger, &estates);
        assert!(
            other.owned.is_empty() && other.missing.is_empty(),
            "{other:?}"
        );
        assert_eq!(other.orphans.len(), 1, "{other:?}");

        // Twin: without the laid record, every one of them is an orphan again.
        let bare = cloud_inventory_pb("gunnar", &cloud, &s.ledger, &EstateIron::default());
        assert_eq!(bare.orphans.len(), 9, "{bare:?}");
    }

    /// A gone run owns nothing, a run not yet laid owns nothing, and an id the
    /// give-back already asked to go is not "missing".
    #[test]
    fn a_gone_or_unlaid_run_owns_nothing_and_a_given_back_id_is_not_missing() {
        let laid = acme_laid();
        assert_eq!(
            LaidIron::from_parts(phase::TERMINATED, "estate/acme", Some(&laid), &[]),
            None
        );
        assert_eq!(
            LaidIron::from_parts(phase::RELEASED, "estate/acme", Some(&laid), &[]),
            None
        );
        assert_eq!(
            LaidIron::from_parts(phase::LAYING, "estate/acme", None, &[]),
            None
        );
        let terminating = LaidIron::from_parts(
            phase::TERMINATING,
            "estate/acme",
            Some(&laid),
            &["server/srv-front".into()],
        )
        .unwrap();
        let rows = estate_holdings("upcloud", &[], &[terminating]);
        assert_eq!(rows.len(), 8, "front's server was given back; its disks and the other boxes are still missing: {rows:?}");
        assert!(
            rows.iter().all(|h| h.reference == "estate/acme"
                && h.id.as_ref().is_some_and(|i| i.provider == "upcloud")),
            "{rows:?}"
        );
        assert!(
            !rows
                .iter()
                .any(|h| h.id.as_ref().unwrap().id == "srv-front"),
            "{rows:?}"
        );
    }

    /// One site's laid record: front, main and twin, one disk each, under `estate/<company>`.
    fn site_laid(company: &str) -> LaidEstate {
        let mut l = acme_laid();
        l.reference = format!("estate/{company}");
        l.company = company.into();
        for m in &mut l.machines {
            m.server = format!("{company}-{}", m.role);
            m.disks.truncate(1);
            m.disks[0].id = format!("{company}-{}-disk", m.role);
        }
        l
    }

    /// **RED MAP-SEG 1 (owner 2026-10-26, the Map of test2-gunnar-rs):** the Map of ONE estate
    /// listed the cloud iron of EVERY estate on the account (rickardtest, acme2, ignalina,
    /// test2holgerrs, holgerrs, test2gunnarrs), because no row said whose it was. Every row
    /// of the inventory now names its estate — a site's by its LABEL (the name its
    /// `/e/<estate>/` pages carry), a sold estate's by its company, a tenant's holding of a
    /// sold estate by that estate — and a row of no ONE estate names none.
    #[test]
    fn every_inventory_row_names_the_estate_it_belongs_to() {
        use monetize_cloud::OwnedKind;
        let s = state();
        let mut at_provider = Vec::new();
        for (company, roles) in [
            ("test2gunnarrs", ["front", "main", "twin"]),
            ("acme", ["front", "main", "twin"]),
        ] {
            for role in roles {
                at_provider.push(listed(
                    &format!("server/{company}-{role}"),
                    OwnedKind::Server,
                    &format!("estate/{company}"),
                ));
                at_provider.push(listed(
                    &format!("storage/{company}-{role}-disk"),
                    OwnedKind::Disk,
                    &format!("estate/{company}"),
                ));
            }
        }
        at_provider.push(listed(
            "storage/left-behind",
            OwnedKind::Disk,
            "estate/holgerr34e",
        ));
        let cloud = Listed(at_provider);
        let estates = EstateIron {
            product: Some("gunnar".into()),
            laid: vec![
                LaidIron::from_parts(
                    phase::CAPTURED,
                    "estate/test2gunnarrs",
                    Some(&site_laid("test2gunnarrs")),
                    &[],
                )
                .unwrap()
                .named("test2-gunnar-rs"),
                LaidIron::from_parts(
                    phase::CAPTURED,
                    "estate/acme",
                    Some(&site_laid("acme")),
                    &[],
                )
                .unwrap()
                .named("acme"),
            ],
        };
        let c = cloud_inventory_pb("gunnar", &cloud, &s.ledger, &estates);
        assert_eq!(c.owned.len(), 12, "{c:?}");
        for o in &c.owned {
            let want = if o.reference == "estate/acme" {
                "acme"
            } else {
                "test2-gunnar-rs"
            };
            assert_eq!(o.estate, want, "a row says whose it is: {o:?}");
        }
        assert_eq!(
            c.orphans
                .iter()
                .map(|o| (o.id.as_str(), o.estate.as_str()))
                .collect::<Vec<_>>(),
            vec![("storage/left-behind", "holgerr34e")],
            "an orphan's label still names the estate it was laid for: {c:?}"
        );
        // The rule itself, every arm.
        assert_eq!(
            estate_of("estate/test2gunnarrs", &estates.laid),
            "test2-gunnar-rs"
        );
        assert_eq!(estate_of("estate/gone2", &estates.laid), "gone2");
        assert_eq!(
            estate_of("gunnar/@acme/team/2026-10-01", &estates.laid),
            "acme"
        );
        assert_eq!(
            estate_of("gunnar/alice/2026-10-01", &estates.laid),
            "",
            "a product's own tenant is no ONE estate's"
        );
        assert_eq!(estate_of("", &estates.laid), "");
    }

    /// A cloud whose labelled listing is `listed` and where the unlabelled `standing` ids stand
    /// (a kit's machines): `status` answers by uuid, as UpCloud's `GET /server/<uuid>` does.
    struct Standing {
        listed: Vec<monetize_cloud::Owned>,
        standing: Vec<String>,
    }
    impl Standing {
        pub fn provider(&self) -> &'static str {
            "upcloud"
        }
        pub fn zones(&self) -> &[monetize_cloud::Zone] {
            &[]
        }
        pub fn price_resource(
            &self,
            _: &monetize_cloud::Resource,
        ) -> Result<monetize_cloud::Price, monetize_cloud::CloudError> {
            Err(monetize_cloud::CloudError::Refused(
                "not in this test".into(),
            ))
        }
        pub fn ensure(
            &self,
            _: &str,
            _: &monetize_cloud::Resource,
        ) -> Result<monetize_cloud::Ensured, monetize_cloud::CloudError> {
            Err(monetize_cloud::CloudError::Refused(
                "nothing is bought in this test".into(),
            ))
        }
        pub fn destroy_id(
            &self,
            _: &monetize_cloud::ResourceId,
        ) -> Result<(), monetize_cloud::CloudError> {
            panic!("the panel never cleans anything up")
        }
        pub fn status(
            &self,
            id: &monetize_cloud::ResourceId,
        ) -> Result<monetize_cloud::ResourceStatus, monetize_cloud::CloudError> {
            let bare = id.id.rsplit('/').next().unwrap_or_default();
            Ok(if self.standing.iter().any(|s| s == bare) {
                monetize_cloud::ResourceStatus::Active
            } else {
                monetize_cloud::ResourceStatus::Gone
            })
        }
        pub fn list_owned(&self) -> Result<monetize_cloud::Inventory, monetize_cloud::CloudError> {
            Ok(monetize_cloud::Inventory {
                owned: self.listed.clone(),
                foreign: 6,
                currency: monetize_pay::Currency::Eur,
            })
        }
    }
    impl monetize_cloud::cloud::Cloud for Standing {
        fn manifest(&self) -> monetize_cloud::cloud::CloudManifest {
            monetize_cloud::cloud::CloudManifest {
                provider: self.provider().to_string(),
                zones: self.zones().to_vec(),
                settings: Vec::new(),
                grow_refused: Some(monetize_cloud::grow::unsupported(self.provider()).to_string()),
            }
        }
        fn catalog(
            &self,
            _zone: &monetize_cloud::Zone,
        ) -> Result<monetize_cloud::cloud::Catalog, monetize_cloud::CloudError> {
            Err(monetize_cloud::lay::unsupported(self.provider()))
        }
        fn price(
            &self,
            what: &monetize_cloud::cloud::Priced<'_>,
        ) -> Result<monetize_cloud::Price, monetize_cloud::CloudError> {
            match what {
                monetize_cloud::cloud::Priced::Resource(r) => self.price_resource(r),
                monetize_cloud::cloud::Priced::Plan(p) => {
                    monetize_cloud::price_estate_by_rows(p, |r| self.price_resource(r), None)
                }
                monetize_cloud::cloud::Priced::Grow(_set) => {
                    Err(monetize_cloud::grow::unsupported(self.provider()))
                }
            }
        }
        fn lay(
            &self,
            _plan: &monetize_cloud::lay::EstatePlan,
            _journal: &monetize_cloud::grow::Journal,
        ) -> Result<monetize_cloud::lay::LaidEstate, monetize_cloud::CloudError> {
            Err(monetize_cloud::lay::unsupported(self.provider()))
        }
        fn change(
            &self,
            change: &monetize_cloud::cloud::Change,
            _journal: &monetize_cloud::grow::Journal,
        ) -> Result<monetize_cloud::cloud::Changed, monetize_cloud::CloudError> {
            Ok(match change {
                monetize_cloud::cloud::Change::Plan {
                    server: _,
                    plan: _,
                    delta: _,
                } => {
                    return Err(monetize_cloud::lay::unsupported_verb(
                        self.provider(),
                        "change_plan",
                    ))
                }
                monetize_cloud::cloud::Change::Grow { set: _, estate: _ } => {
                    return Err(monetize_cloud::grow::unsupported(self.provider()))
                }
                monetize_cloud::cloud::Change::Settle { set: _ } => {
                    return Err(monetize_cloud::grow::unsupported(self.provider()))
                }
                monetize_cloud::cloud::Change::ForgetMedia { laid: _ } => {
                    monetize_cloud::cloud::Changed::Forgotten(Vec::new())
                }
                monetize_cloud::cloud::Change::Ensure {
                    reference,
                    resource,
                    room: _,
                } => monetize_cloud::cloud::Changed::Ensured(self.ensure(reference, resource)?),
                monetize_cloud::cloud::Change::Retire { reference, machine } => {
                    monetize_cloud::cloud::Changed::Retired(monetize_cloud::cloud::retire_by_rows(
                        self, reference, machine,
                    )?)
                }
                monetize_cloud::cloud::Change::LabelAdopted { .. } => {
                    return Err(monetize_cloud::lay::unsupported_verb(
                        self.provider(),
                        "label_adopted",
                    ))
                }
            })
        }
        fn boot(
            &self,
            boot: &monetize_cloud::cloud::Boot,
            _journal: &monetize_cloud::grow::Journal,
        ) -> Result<monetize_cloud::cloud::Booted, monetize_cloud::CloudError> {
            match boot {
                monetize_cloud::cloud::Boot::Keep(_k) => Err(
                    monetize_cloud::lay::unsupported_verb(self.provider(), "keep_boot"),
                ),
                monetize_cloud::cloud::Boot::Power { server: _, on: _ } => Err(
                    monetize_cloud::lay::unsupported_verb(self.provider(), "set_power"),
                ),
                monetize_cloud::cloud::Boot::Restore(_r) => Err(
                    monetize_cloud::lay::unsupported_verb(self.provider(), "restore_from_backup"),
                ),
            }
        }
        fn firewall(
            &self,
            _laid: &monetize_cloud::lay::LaidEstate,
        ) -> Result<(), monetize_cloud::CloudError> {
            Err(monetize_cloud::lay::unsupported_verb(
                self.provider(),
                "set_estate_firewall",
            ))
        }
        fn destroy(
            &self,
            what: &monetize_cloud::cloud::Give<'_>,
        ) -> Result<monetize_cloud::Reclaimed, monetize_cloud::CloudError> {
            match what {
                monetize_cloud::cloud::Give::References(refs) => Ok(
                    monetize_cloud::release_for_by_rows(self.list_owned()?, refs, |id| {
                        self.destroy_id(id)
                    }),
                ),
                monetize_cloud::cloud::Give::Resource(id) => {
                    self.destroy_id(id)?;
                    Ok(monetize_cloud::Reclaimed {
                        destroyed: vec![(*id).clone()],
                        ..monetize_cloud::Reclaimed::default()
                    })
                }
            }
        }
        fn inventory(
            &self,
            what: &monetize_cloud::cloud::Listing<'_>,
        ) -> Result<monetize_cloud::cloud::Listed, monetize_cloud::CloudError> {
            Ok(match what {
                monetize_cloud::cloud::Listing::Account => {
                    monetize_cloud::cloud::Listed::Account(self.list_owned()?)
                }
                monetize_cloud::cloud::Listing::Set(_set) => {
                    return Err(monetize_cloud::grow::unsupported(self.provider()))
                }
                monetize_cloud::cloud::Listing::Status(id) => {
                    monetize_cloud::cloud::Listed::Status(self.status(id)?)
                }
                monetize_cloud::cloud::Listing::Under(refs) => {
                    monetize_cloud::cloud::Listed::Under(monetize_cloud::cloud::under(
                        self.list_owned()?,
                        refs,
                    ))
                }
                monetize_cloud::cloud::Listing::Room { delta: _, room: _ } => {
                    monetize_cloud::cloud::Listed::Room(monetize_cloud::cloud::RoomLeft {
                        serve: Ok(()),
                        left_bytes: None,
                        ceilings: Default::default(),
                    })
                }
                monetize_cloud::cloud::Listing::Admits(_plan) => {
                    monetize_cloud::cloud::Listed::Admitted
                }
            })
        }
    }

    /// **RED MAP-SEG 4 (owner 2026-10-26: "3 MISSING gunnarrs servers"):** gunnar.rs was
    /// installed by its kit and ADOPTED by the ONE box. Its machines stand on this box's account
    /// (the box keep-booted its front through it) but carry no label of this box, so the
    /// labelled listing never holds them, and the panel called all three "sold, but the cloud
    /// does not have it". The inventory now looks an adopted estate's machines up BY UUID: the
    /// three that stand are owned under the estate, not missing — and a machine that is really
    /// gone still IS missing.
    #[test]
    fn an_adopted_estates_standing_machines_are_owned_and_a_gone_one_is_missing() {
        let s = state();
        let adopted = LaidIron::from_parts(
            phase::CAPTURED,
            "estate/gunnarrs",
            Some(&site_laid("gunnarrs")),
            &[],
        )
        .unwrap()
        .named("gunnar-rs")
        .adopted_if(true);
        let estates = EstateIron {
            product: Some("gunnar".into()),
            laid: vec![adopted],
        };
        let all: Vec<String> = ["front", "main", "twin"]
            .iter()
            .flat_map(|r| [format!("gunnarrs-{r}"), format!("gunnarrs-{r}-disk")])
            .collect();
        let c = cloud_inventory_pb(
            "gunnar",
            &Standing {
                listed: Vec::new(),
                standing: all.clone(),
            },
            &s.ledger,
            &estates,
        );
        assert!(
            c.missing.is_empty(),
            "an adopted estate whose machines stand is not missing: {:?}",
            c.missing
        );
        assert_eq!(
            c.owned.len(),
            6,
            "its 3 servers and 3 disks are owned under it: {c:?}"
        );
        assert!(
            c.owned
                .iter()
                .all(|o| o.estate == "gunnar-rs" && o.reference == "estate/gunnarrs" && !o.priced),
            "{c:?}"
        );
        assert!(c.orphans.is_empty(), "{c:?}");
        // The main is really gone: it, and its disk, ARE missing.
        let left: Vec<String> = all
            .iter()
            .filter(|i| !i.starts_with("gunnarrs-main"))
            .cloned()
            .collect();
        let c = cloud_inventory_pb(
            "gunnar",
            &Standing {
                listed: Vec::new(),
                standing: left,
            },
            &s.ledger,
            &estates,
        );
        let mut gone: Vec<&str> = c.missing.iter().map(|m| m.id.as_str()).collect();
        gone.sort();
        assert_eq!(
            gone,
            vec!["gunnarrs-main", "gunnarrs-main-disk"],
            "{:?}",
            c.missing
        );
        assert!(c.missing.iter().all(|m| m.estate == "gunnar-rs"));
    }

    /// A provider-side BACKUP row as UpCloud lists one: a storage of type backup, with the
    /// `origin` it was taken of, the labels of that disk copied onto it (`reference`), or
    /// none (a kit's disk, the ONE box's own disk).
    fn backup(
        id: &str,
        origin: &str,
        standing: bool,
        server: &str,
        created: &str,
        reference: Option<&str>,
        title: &str,
    ) -> monetize_cloud::Owned {
        let mut b = listed(
            id,
            monetize_cloud::OwnedKind::Disk,
            reference.unwrap_or_default(),
        );
        b.reference = reference.map(str::to_owned);
        b.gib = 10;
        b.monthly_minor = None;
        b.backup = Some(monetize_cloud::BackupOf {
            origin: origin.into(),
            origin_standing: standing,
            server: server.into(),
            created: created.into(),
            title: title.into(),
        });
        b
    }

    /// **RED MAP-3 (owner 2026-10-27, the ONE box's Iron page):** 16 UpCloud BACKUPS of the
    /// live estates holger-rs, test2-gunnar-rs and test2-holger-rs ("Simple backup of
    /// gunnar-front-test2gunnarrs system", …) read "⚠ orphan — we pay for this and no order
    /// owns it": a backup carries the labels of the disk it was taken of, and no order laid it.
    /// A backup belongs to the estate of its ORIGIN disk: it is listed under that estate as
    /// `backup of <server>, <date>`, counted apart from the owned disks, never as an orphan.
    /// A backup whose disk is gone is an orphan, by its title. The daily backups of a kit
    /// estate the box adopted (gunnar-rs, "Scheduled backup of gunnar-front") belong to it
    /// the same way, and the ONE box's own disk's ("monetize-prod") are the account's own,
    /// no estate's: a backup, not an orphan either.
    #[test]
    fn a_backup_belongs_to_its_disks_estate_and_is_an_orphan_only_when_its_disk_is_gone() {
        use monetize_cloud::OwnedKind;
        let s = state();
        let mut listed_rows = Vec::new();
        for role in ["front", "main", "twin"] {
            listed_rows.push(listed(
                &format!("server/test2gunnarrs-{role}"),
                OwnedKind::Server,
                "estate/test2gunnarrs",
            ));
            let mut d = listed(
                &format!("storage/test2gunnarrs-{role}-disk"),
                OwnedKind::Disk,
                "estate/test2gunnarrs",
            );
            d.attached_to = Some(format!("test2gunnarrs-{role}"));
            listed_rows.push(d);
        }
        let front = "storage/test2gunnarrs-front-disk";
        let site = |id: &str, created: &str| {
            backup(
                id,
                front,
                true,
                "gunnar-front-test2gunnarrs",
                created,
                Some("estate/test2gunnarrs"),
                "Simple backup of gunnar-front-test2gunnarrs system",
            )
        };
        listed_rows.push(site("storage/bk-site-27", "2026-10-27T03:56:43Z"));
        listed_rows.push(site("storage/bk-site-26", "2026-10-26T03:51:35Z"));
        // Of a disk that is gone: an orphan, named.
        listed_rows.push(backup(
            "storage/bk-gone",
            "storage/old-front-disk",
            false,
            "",
            "2026-10-20T04:00:00Z",
            Some("estate/test2gunnarrs"),
            "Simple backup of gunnar-front-old system",
        ));
        // Of the adopted gunnar-rs front (its disk carries no label, nor does its backup).
        listed_rows.push(backup(
            "storage/bk-adopted",
            "storage/gunnarrs-front-disk",
            true,
            "gunnar-front",
            "2026-10-27T03:58:58Z",
            None,
            "Scheduled backup of gunnar-front system",
        ));
        // Of the ONE box's own disk: the account's own, no estate's.
        listed_rows.push(backup(
            "storage/bk-box",
            "storage/monetize-prod-disk",
            true,
            "monetize-prod",
            "2026-10-27T03:48:43Z",
            None,
            "Scheduled backup of monetize-prod system",
        ));
        // Of a labelled disk no order laid (itself an orphan): an orphan too.
        let mut stray = listed("storage/stray", OwnedKind::Disk, "estate/ghost");
        stray.gib = 40;
        listed_rows.push(stray);
        listed_rows.push(backup(
            "storage/bk-stray",
            "storage/stray",
            true,
            "",
            "2026-10-27T01:00:00Z",
            Some("estate/ghost"),
            "Simple backup of ghost system",
        ));

        let adopted = LaidIron::from_parts(
            phase::CAPTURED,
            "estate/gunnarrs",
            Some(&site_laid("gunnarrs")),
            &[],
        )
        .unwrap()
        .named("gunnar-rs")
        .adopted_if(true);
        let site_run = LaidIron::from_parts(
            phase::CAPTURED,
            "estate/test2gunnarrs",
            Some(&site_laid("test2gunnarrs")),
            &[],
        )
        .unwrap()
        .named("test2-gunnar-rs");
        let estates = EstateIron {
            product: Some("gunnar".into()),
            laid: vec![site_run, adopted],
        };
        let standing: Vec<String> = ["front", "main", "twin"]
            .iter()
            .flat_map(|r| [format!("gunnarrs-{r}"), format!("gunnarrs-{r}-disk")])
            .collect();
        let cloud = Standing {
            listed: listed_rows,
            standing,
        };

        let c = cloud_inventory_pb("gunnar", &cloud, &s.ledger, &estates);
        assert!(c.available, "{}", c.error);
        // Owned: the site's 6 and the adopted estate's 6 — no backup among them.
        assert!(
            c.owned.iter().all(|o| !o.id.starts_with("storage/bk-")),
            "a backup is never an owned disk: {:?}",
            c.owned
        );
        assert_eq!(c.owned.len(), 12, "{:?}", c.owned);
        assert_eq!(c.total_bytes, 9 * 20 * GIB, "the totals are the owned rows' alone (6 listed, 3 adopted disks), no backup in them: {c:?}");
        // The orphans: the stray disk, its backup, and the backup of a gone disk, by title.
        let mut orphans: Vec<(&str, &str)> = c
            .orphans
            .iter()
            .map(|o| (o.id.as_str(), o.title.as_str()))
            .collect();
        orphans.sort();
        assert_eq!(
            orphans,
            vec![
                (
                    "storage/bk-gone",
                    "Simple backup of gunnar-front-old system"
                ),
                ("storage/bk-stray", "Simple backup of ghost system"),
                ("storage/stray", "")
            ],
            "{:?}",
            c.orphans
        );
        assert!(
            c.orphans
                .iter()
                .filter(|o| o.id.starts_with("storage/bk-"))
                .all(|o| o.kind == "backup"),
            "an orphan backup says it is a backup: {:?}",
            c.orphans
        );
        // The backups: each under its disk's estate, in words.
        let got: Vec<(&str, &str, &str)> = c
            .backups
            .iter()
            .map(|b| (b.id.as_str(), b.estate.as_str(), b.words.as_str()))
            .collect();
        assert_eq!(
            got,
            vec![
                (
                    "storage/bk-site-27",
                    "test2-gunnar-rs",
                    "backup of gunnar-front-test2gunnarrs, 2026-10-27"
                ),
                (
                    "storage/bk-site-26",
                    "test2-gunnar-rs",
                    "backup of gunnar-front-test2gunnarrs, 2026-10-26"
                ),
                (
                    "storage/bk-adopted",
                    "gunnar-rs",
                    "backup of gunnar-front, 2026-10-27"
                ),
                ("storage/bk-box", "", "backup of monetize-prod, 2026-10-27"),
            ],
            "{:?}",
            c.backups
        );
        assert!(
            c.backups
                .iter()
                .all(|b| b.gib == 10 && b.created.starts_with("2026-10-2") && !b.origin.is_empty()),
            "{:?}",
            c.backups
        );
        assert_eq!(
            c.backup_bytes,
            4 * 10 * GIB,
            "counted apart from the owned disks"
        );
        // Another product's panel lists the same backups and orphans: they are estates', not a product's.
        let other = cloud_inventory_pb("holger", &cloud, &s.ledger, &estates);
        assert_eq!(other.backups.len(), 4, "{other:?}");
        assert_eq!(other.orphans.len(), 3, "{other:?}");
        assert!(other.owned.is_empty(), "{other:?}");
    }
}