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

nordisk/monetize

fuzz/src/lib.rs

//! **monetize's fuzz entry points.** One function per target in `fuzz_targets/`, each taking
//! the bytes a stranger chose and handing them to the code monetize runs on them. Each
//! returns whether the input was ACCEPTED (it verified, parsed or was taken), which
//! `tests/seeds.rs` uses to prove the committed `ok-*` seeds still reach the deep end of
//! their parser. A panic, an overflow or a hang here is the bug a fuzzer is looking for.
//!
//! **The modes.** Most inputs are signed, and a mutated signature never verifies, so a
//! fuzzer that only mutated bytes would only ever explore the refusal. The first byte of a
//! signed target's input picks a mode: an even byte hands the rest to the code exactly as it
//! came (the refusal path: header, envelope, signature parsing); an odd byte lets the harness
//! SIGN what the rest says with the throwaway key the code under test trusts, so the
//! mutations reach the parsers that only run on a verified input. Neither mode skips any
//! check of the code under test: the harness only plays the honest signer.
//!
//! The keys and secrets below are throwaway test values derived from constants: nothing secret.

use std::collections::BTreeMap;
use std::sync::{Arc, OnceLock};

use monetize_embed::fleet::{FleetCall, OrderAck, SignedOrder};
use monetize_estate_side::pump::{
    Addressee, Asked, Asker, BoxKey, Ctx, Fault, Link, Puller, PumpBox, Signed,
};
use monetize_pay::invoice::{InvoiceConfig, InvoiceProvider, IMPORT_TOKEN_HEADER};
use monetize_pay::sandbox::{SandboxConfig, SandboxProvider, SIGNATURE_HEADER};
use monetize_pay::{ChargeRequest, Market, Money, PayError, RawCallback};
use prost::Message;

/// The clock every target runs at (2027-01-15T08:00:00Z).
pub const NOW: u64 = 1_800_000_000_000;
/// The sandbox vendor's throwaway callback secret.
pub const SANDBOX_SECRET: &str = "fuzz-sandbox-secret";
/// The invoice importer's throwaway token.
pub const IMPORT_TOKEN: &str = "fuzz-import-token";
/// The reference the harness reserves at each vendor (so a callback can name an open charge).
pub const REFERENCE: &str = "fuzzprod/acme/2027";
/// The product, estate and box the Fleet targets speak as.
pub const PRODUCT: &str = "fuzzprod";
pub const INSTANCE: &str = "acme";
/// monetize's throwaway signing seed (the product key the facts, go-aheads and orders are signed with).
pub const MONETIZE_SEED: [u8; 32] = [7u8; 32];
/// A box's throwaway fleet key seed (main, twin and front: one key each).
pub fn box_seed(role: &str) -> [u8; 32] {
    match role {
        "main" => [11u8; 32],
        "twin" => [12u8; 32],
        _ => [13u8; 32],
    }
}

/// monetize's throwaway signer.
pub fn monetize_signer() -> monetize::Signer {
    monetize::Signer::from_bytes(&MONETIZE_SEED)
}

fn odd(mode: u8) -> bool {
    mode & 1 == 1
}

// ── framing ───────────────────────────────────────────────────────────────────

/// An HTTP-ish delivery: `name: value` header lines, an empty line, then the body.
pub fn split_http(data: &[u8]) -> (Vec<(String, String)>, Vec<u8>) {
    let at = data.windows(2).position(|w| w == b"\n\n");
    let (head, body) = match at {
        Some(i) => (&data[..i], &data[i + 2..]),
        None => (&data[..0], data),
    };
    let headers = String::from_utf8_lossy(head)
        .lines()
        .filter_map(|l| {
            l.split_once(':')
                .map(|(k, v)| (k.trim().to_string(), v.trim().to_string()))
        })
        .collect();
    (headers, body.to_vec())
}

/// The inverse of [`split_http`], for the seeds.
pub fn http(headers: &[(&str, &str)], body: &[u8]) -> Vec<u8> {
    let mut out = Vec::new();
    for (k, v) in headers {
        out.extend_from_slice(format!("{k}: {v}\n").as_bytes());
    }
    out.extend_from_slice(b"\n");
    out.extend_from_slice(body);
    out
}

fn verified<T>(r: &Result<T, PayError>) -> bool {
    matches!(
        r,
        Ok(_) | Err(PayError::Signup(_)) | Err(PayError::Ignored(_))
    )
}

fn req(reference: &str, market: Market) -> ChargeRequest {
    ChargeRequest {
        reference: reference.into(),
        amount: Money {
            minor: 12_500,
            currency: market.currency(),
        },
        market,
        description: "fuzz".into(),
        payer: None,
    }
}

// ── pay_callback ──────────────────────────────────────────────────────────────

/// **A payment vendor's callback** (`POST /callback/<kind>/<instance>`), on the open vendors:
/// the sandbox (its JSON body, its signature header, the signup arm, the row it names) and
/// the invoice importer (the import token, a BgMax/KTL bank file, the OCR check digits, the
/// number it minted). Mode (first byte) 0 = sandbox as sent, 1 = sandbox with the harness's
/// signature (`@H` in the body is replaced by the handle the harness reserved), 2 = invoice.
pub fn pay_callback(data: &[u8]) -> bool {
    let Some((&mode, rest)) = data.split_first() else {
        return false;
    };
    let (mut headers, mut body) = split_http(rest);
    match mode % 3 {
        2 => {
            let p = InvoiceProvider::new(InvoiceConfig {
                import_token: IMPORT_TOKEN.into(),
                bankgiro: None,
            });
            for m in [Market::Se, Market::Fi] {
                let _ = p.reserve(&req(REFERENCE, m));
            }
            let _ = monetize_pay::invoice::bankfile::parse_with_fallback_date(&body, NOW);
            if let Ok(text) = std::str::from_utf8(&body) {
                let _ = monetize_pay::time::parse_rfc3339_ms(text);
                let _ = monetize_pay::invoice::ocr::bankgiro_verify(text.trim());
                let _ = monetize_pay::invoice::ocr::finnish_verify(text.trim());
            }
            verified(&p.parse_callback(RawCallback {
                headers: &headers,
                body: &body,
            }))
        }
        m => {
            let p = SandboxProvider::new(SandboxConfig {
                callback_secret: SANDBOX_SECRET.into(),
                state_path: None,
            })
            .with_clock(|| NOW);
            let Ok(handle) = p.reserve(&req(REFERENCE, Market::Se)) else {
                return false;
            };
            if m == 1 {
                body = replace(&body, b"@H", handle.id.as_bytes());
                if let Ok(v) = serde_json::from_slice::<serde_json::Value>(&body) {
                    let sig = match v.get("signup").and_then(|s| s.as_str()) {
                        Some(session) => SandboxProvider::signup_signature(SANDBOX_SECRET, session),
                        None => SandboxProvider::signature(
                            SANDBOX_SECRET,
                            v.get("reference").and_then(|s| s.as_str()).unwrap_or(""),
                            v.get("handle").and_then(|s| s.as_str()).unwrap_or(""),
                        ),
                    };
                    headers.push((SIGNATURE_HEADER.to_string(), sig));
                }
            }
            verified(&p.parse_callback(RawCallback {
                headers: &headers,
                body: &body,
            }))
        }
    }
}

fn replace(hay: &[u8], needle: &[u8], with: &[u8]) -> Vec<u8> {
    let mut out = Vec::with_capacity(hay.len());
    let mut i = 0;
    while i < hay.len() {
        if hay[i..].starts_with(needle) {
            out.extend_from_slice(with);
            i += needle.len();
        } else {
            out.push(hay[i]);
            i += 1;
        }
    }
    out
}

// ── feed_config ───────────────────────────────────────────────────────────────

/// **The operator's feed and monetize's configuration** (TOML; monetize reads no RON). Mode
/// (first byte) even: the rest is a feed (a JSON object of strings, as `PUT /feed` takes it)
/// through every intake reader the ONE box applies (plugins and their blocks and prices,
/// secrets, vendors, control principals, clouds and the other guests, the operator's
/// `monetize.toml`) and the estate side's readers of the same feed (the box pump's fleet
/// config, the front's shop door). Odd: the rest is a `monetize.toml` (the whole config with
/// its checks, a `[products.<id>]` block, a `[vendors.<kind>.<instance>]` block).
pub fn feed_config(data: &[u8]) -> bool {
    let Some((&mode, rest)) = data.split_first() else {
        return false;
    };
    if odd(mode) {
        let Ok(text) = std::str::from_utf8(rest) else {
            return false;
        };
        let _ = toml::from_str::<monetize_server::config::ProductConfig>(text);
        let _ = toml::from_str::<monetize_server::config::VendorConfig>(text);
        return monetize_server::config::Config::from_toml(text).is_ok();
    }
    let Ok(feed) = serde_json::from_slice::<BTreeMap<String, String>>(rest) else {
        return false;
    };
    use monetize_front::intake;
    let (plugins, roots, mut refused) = intake::plugins(&feed);
    let (secrets, r) = intake::secrets(&feed);
    refused.extend(r);
    let (vendors, r) = intake::vendors(&feed);
    refused.extend(r);
    let (_, r) = intake::control_principals(&feed);
    refused.extend(r);
    let (_, r) = intake::operator_toml(&feed);
    refused.extend(r);
    let (clouds, r) = intake::clouds(&feed);
    refused.extend(r);
    for prefix in ["signup_guest.", "dns_guest."] {
        let _ = intake::modules_at(&feed, prefix);
    }
    let _ = monetize_estate_side::pump::FleetConfig::from_feed(&feed).map(|c| c.key());
    let _ = monetize_estate_side::sold_door::ShopDoor::from_feed(&feed);
    let _ = (roots, secrets);
    refused.is_empty() && (!plugins.is_empty() || !vendors.is_empty() || !clouds.is_empty())
}

// ── signed_facts ──────────────────────────────────────────────────────────────

/// **What a product checks before it believes monetize** (monetize-embed): a signed snapshot
/// (the entitlement cache's `refresh`), one pushed fact, a growth go-ahead, a sold estate's
/// growth, an actor ticket. Mode (first byte) even: the rest as sent, every reader; odd: the
/// harness re-signs what the rest parses as (a snapshot, else a go-ahead) with monetize's
/// throwaway key, so the mutations reach what runs after the signature.
pub fn signed_facts(data: &[u8]) -> bool {
    let Some((&mode, rest)) = data.split_first() else {
        return false;
    };
    let signer = monetize_signer();
    let key = signer.verifying_key();
    let Ok(cache) = monetize_embed::EntitlementCache::new(
        &signer.public_key(),
        "https://fuzz.invalid/billing/{tenant}",
    ) else {
        return false;
    };
    if odd(mode) {
        if let Ok(snap) = serde_json::from_slice::<monetize_embed::signing::Snapshot>(rest) {
            let facts = snap
                .facts
                .into_iter()
                .map(|f| signer.sign_fact_at(f, snap.issued_unix_ms))
                .collect();
            let snap = signer.sign_snapshot(snap.issued_unix_ms, facts);
            let Ok(bytes) = serde_json::to_vec(&snap) else {
                return false;
            };
            let n = cache.refresh(&bytes);
            for f in &snap.facts {
                let _ = cache.allows(&f.tenant, monetize_embed::Action::Write);
                let _ = cache.notice(&f.tenant);
            }
            return n.is_ok();
        }
        if let Ok(go) = serde_json::from_slice::<monetize_embed::signing::GoAhead>(rest) {
            let bytes = signer.sign_go_ahead(go.target_sectors, &go.nonce, go.issued_unix_ms);
            return monetize_embed::signing::verify_go_ahead(&bytes, &key).is_ok();
        }
        return false;
    }
    let mut accepted = cache.refresh(rest).is_ok();
    if let Ok(fact) = serde_json::from_slice::<monetize_product::EntitlementFact>(rest) {
        accepted |= cache.push(fact).is_ok();
    }
    accepted |= monetize_embed::signing::verify_go_ahead(rest, &key).is_ok();
    accepted |= monetize_embed::signing::verify_estate_growth(rest, &key).is_ok();
    accepted |= monetize_embed::ticket::verify_ticket(
        rest,
        &key,
        PRODUCT,
        INSTANCE,
        "push",
        &BTreeMap::new(),
        NOW as i64,
    )
    .is_ok();
    if let Ok(text) = std::str::from_utf8(rest) {
        let _ = monetize_embed::signing::base64_decode(text);
    }
    accepted
}

// ── fleet_door ────────────────────────────────────────────────────────────────

struct Door {
    guardian: monetize_guardian::Guardian,
}

fn door() -> &'static Door {
    static DOOR: OnceLock<Door> = OnceLock::new();
    DOOR.get_or_init(|| {
        let store =
            Arc::new(monetize_guardian::Store::in_memory().expect("an in-memory guardian store"));
        store
            .declare(INSTANCE, PRODUCT)
            .expect("declare the estate");
        for role in ["main", "twin", "front"] {
            let public = BoxKey::from_seed(box_seed(role)).public();
            store
                .register_key(
                    INSTANCE,
                    role,
                    &monetize_embed::signing::base64_encode(&public),
                )
                .expect("register a box key");
        }
        // An estate being laid: a new box may pin its key on its first call.
        store
            .open_pin(INSTANCE, "new", NOW + 3_600_000)
            .expect("open a pin window");
        let keys = Arc::new(monetize::Keyring::new(monetize_signer()));
        let guardian = monetize_guardian::Guardian::new(
            store,
            keys,
            monetize_guardian::GuardianConfig {
                looks_in_tick: false,
                ..Default::default()
            },
        );
        Door { guardian }
    })
}

/// **The Fleet door** (`Fleet.Report`, `Fleet.Orders`, `Fleet.Ask`, the old sold-estate door
/// folded into `Fleet.Ask`): the rest is a protobuf `FleetSigned` as tonic hands it over;
/// the guardian authenticates it (the box key registered for the estate and role, the time
/// window) or pins a new box's key, then reads its JSON body (a report, an orders request,
/// an ask, a front's ask). Mode (first byte) odd: the harness signs the call as the box it
/// names (`main`, `twin`, `front`) at [`NOW`].
pub fn fleet_door(data: &[u8]) -> bool {
    let Some((&mode, rest)) = data.split_first() else {
        return false;
    };
    let Ok(wire) = monetize_proto::FleetSigned::decode(rest) else {
        return false;
    };
    let mut c = FleetCall {
        product: wire.product,
        instance: wire.instance,
        role: wire.role,
        call: wire.call,
        body: wire.body,
        at_unix_ms: wire.at_unix_ms,
    };
    let mut signature = wire.signature;
    if odd(mode) {
        c.at_unix_ms = NOW;
        signature = BoxKey::from_seed(box_seed(&c.role)).sign(&c);
    }
    let g = &door().guardian;
    let _ = g.first_call(&c, &signature, &wire.box_key, NOW);
    if let Ok(ask) = serde_json::from_str::<monetize_embed::fleet::Ask>(&c.body) {
        let _ = serde_json::from_value::<monetize_embed::fleet::FrontAsk>(ask.body.clone());
        let _ = serde_json::from_value::<monetize_embed::fleet::GrowSetAsk>(ask.body);
    }
    match c.call.as_str() {
        "report" => g.report(&c, &signature, NOW).is_ok(),
        "orders" => g.orders(&c, &signature, NOW).is_ok(),
        "ask" => g.ask(&c, &signature, NOW).is_ok(),
        _ => false,
    }
}

// ── fleet_orders ──────────────────────────────────────────────────────────────

/// monetize in memory, as far as a box's pull sees it: it answers the orders it was given.
struct Wire {
    orders: Vec<SignedOrder>,
}

impl Link for Wire {
    fn report(&mut self, _: Signed) -> Result<u64, Fault> {
        Ok(30_000)
    }
    fn orders(&mut self, _: Signed) -> Result<Vec<SignedOrder>, Fault> {
        Ok(std::mem::take(&mut self.orders))
    }
    fn ask(&mut self, _: Signed) -> Result<Asked, Fault> {
        Ok(Asked::default())
    }
}

/// A product's box, as far as an order's body goes: it reads the bodies monetize's own
/// order kinds carry (a growth go-ahead and the go-ahead inside it, a sign-in link, a
/// refeed) and acks the order.
struct Product;

impl PumpBox for Product {
    fn run(&self, ctx: &Ctx, order: &SignedOrder, ask: &mut dyn Asker) -> OrderAck {
        use monetize_embed::fleet::{kind, GrowGoAhead, Refeed, SignInAgain};
        let ok = match order.kind.as_str() {
            kind::GROW_GO_AHEAD => match serde_json::from_str::<GrowGoAhead>(&order.body) {
                Ok(g) => {
                    monetize_embed::signing::verify_go_ahead(g.go_ahead.as_bytes(), ctx.key).is_ok()
                        || monetize_estate_side::pump::grow_set(ask, g.data_gib).is_ok()
                }
                Err(_) => false,
            },
            kind::SIGN_IN_AGAIN => serde_json::from_str::<SignInAgain>(&order.body).is_ok(),
            kind::REFEED => serde_json::from_str::<Refeed>(&order.body).is_ok(),
            kind::RESTATE_ENTITLEMENTS => serde_json::from_str::<serde_json::Value>(&order.body)
                .ok()
                .and_then(|v| {
                    serde_json::from_value::<monetize_embed::signing::Snapshot>(
                        v["snapshot"].clone(),
                    )
                    .ok()
                })
                .is_some_and(|snap| {
                    monetize_embed::signing::verify_snapshot(&snap, ctx.key).is_ok()
                }),
            _ => serde_json::from_str::<serde_json::Value>(&order.body).is_ok(),
        };
        OrderAck {
            seq: order.seq,
            ok,
            detail: String::new(),
            receipt_json: String::new(),
        }
    }
}

/// **The orders a box pulls** (`Fleet.Orders`' answer, as the box decodes it): the rest is a
/// protobuf `FleetOrdersAnswer`; the box's puller checks each order (monetize's signature,
/// for this box, newer than the last, in its window), runs the fresh ones and queues their
/// acks; the answers of the front's asks (the old sold-estate door's messages, prost-encoded
/// in `FleetAskAnswer.answer`) are decoded too. Mode (first byte) odd: the harness signs each
/// order with monetize's throwaway key, so the bodies are read.
pub fn fleet_orders(data: &[u8]) -> bool {
    let Some((&mode, rest)) = data.split_first() else {
        return false;
    };
    if let Ok(a) = monetize_proto::FleetAskAnswer::decode(rest) {
        let _ = monetize_proto::EstateUpgradeResponse::decode(a.answer.as_slice());
        let _ = monetize_proto::EstateRechargeResponse::decode(a.answer.as_slice());
        let _ = monetize_proto::EstateTakeMaterialResponse::decode(a.answer.as_slice());
        let _ = monetize_proto::EstateUpdateTakeResponse::decode(a.answer.as_slice());
        let _ = monetize_proto::EstateUpdateReportResponse::decode(a.answer.as_slice());
    }
    let Ok(answer) = monetize_proto::FleetOrdersAnswer::decode(rest) else {
        return false;
    };
    let signer = monetize_signer();
    let orders: Vec<SignedOrder> = answer
        .orders
        .into_iter()
        .map(monetize_estate_side::pump::grpc::order_of)
        .map(|o| if odd(mode) { signer.sign_order(o) } else { o })
        .collect();
    let me = Addressee {
        product: PRODUCT.into(),
        instance: INSTANCE.into(),
        role: "main".into(),
    };
    let mut puller = Puller::new(me, BoxKey::from_seed(box_seed("main")), "fuzz");
    let mut wire = Wire { orders };
    match puller.pull(&mut wire, &Product, Some(&signer.public_key()), 0, NOW) {
        Ok(pull) => pull.acks.iter().any(|a| a.ok),
        Err(_) => false,
    }
}

// ── seeds ─────────────────────────────────────────────────────────────────────

/// A BgMax TK15 deposit line (the payment date) and one TK20 payment line.
pub fn bgmax_body(reference: &str, minor: u64, yyyymmdd: &str) -> String {
    let tk20 = format!(
        "20{:<8}{:<25}{:0>18}{:<2}{:<2}{:<12}{}",
        "50501055", reference, minor, "  ", "  ", "", " "
    );
    let tk15 = format!(
        "15{:<35}{}{:0>5}{:0>18}{}{:0>8}{}",
        "SE1234567890", yyyymmdd, 1, minor, "SEK", 1, "K"
    );
    format!("{tk15}\r\n{tk20}\r\n")
}

fn with_mode(mode: u8, rest: &[u8]) -> Vec<u8> {
    let mut v = vec![mode];
    v.extend_from_slice(rest);
    v
}

fn fact(tenant: &str) -> monetize_product::EntitlementFact {
    serde_json::from_value(serde_json::json!({
        "tenant": tenant,
        "plan": "fuzzprod/acme/2027+10gb",
        "state": "Paid",
        "paid_until_unix_ms": NOW + 86_400_000,
        "caps": { "pack_quota_bytes": 10_737_418_240u64 },
        "source": "operator",
        "signature": [],
    }))
    .expect("a fact")
}

fn signed_call(role: &str, call: &str, body: &str) -> Vec<u8> {
    let c = FleetCall {
        product: PRODUCT.into(),
        instance: INSTANCE.into(),
        role: role.into(),
        call: call.into(),
        body: body.into(),
        at_unix_ms: NOW,
    };
    let signature = BoxKey::from_seed(box_seed(role)).sign(&c);
    monetize_proto::FleetSigned {
        product: c.product,
        instance: c.instance,
        role: c.role,
        call: c.call,
        body: c.body,
        at_unix_ms: c.at_unix_ms,
        signature,
        box_key: Vec::new(),
    }
    .encode_to_vec()
}

fn wire_order(seq: u64, kind: &str, body: &str, sign: bool) -> monetize_proto::FleetOrder {
    let mut o = SignedOrder {
        seq,
        product: PRODUCT.into(),
        instance: INSTANCE.into(),
        role: "main".into(),
        kind: kind.into(),
        body: body.into(),
        issued_unix_ms: NOW - 1_000,
        not_after_unix_ms: NOW + 600_000,
        signature: Vec::new(),
    };
    if sign {
        o = monetize_signer().sign_order(o);
    }
    monetize_proto::FleetOrder {
        seq: o.seq,
        product: o.product,
        instance: o.instance,
        role: o.role,
        kind: o.kind,
        body: o.body,
        issued_unix_ms: o.issued_unix_ms,
        not_after_unix_ms: o.not_after_unix_ms,
        signature: o.signature,
    }
}

/// **The committed seeds** (target, file name, bytes): `ok-*` ones are accepted by their
/// target, `refused-*` ones walk a refusal. `tests/seeds.rs` writes them (`write_seeds`, ignored).
pub fn seeds() -> Vec<(&'static str, String, Vec<u8>)> {
    let mut out: Vec<(&'static str, String, Vec<u8>)> = Vec::new();
    let mut add =
        |t: &'static str, name: &str, bytes: Vec<u8>| out.push((t, name.to_string(), bytes));

    // pay_callback
    let body = format!(r#"{{"reference":"{REFERENCE}","handle":"@H"}}"#);
    add(
        "pay_callback",
        "ok-sandbox-harness-signed",
        with_mode(
            1,
            &http(&[("content-type", "application/json")], body.as_bytes()),
        ),
    );
    add(
        "pay_callback",
        "ok-sandbox-unknown-signup",
        with_mode(1, &http(&[], br#"{"signup":"cs_fuzz_1"}"#)),
    );
    add(
        "pay_callback",
        "refused-sandbox-forged",
        with_mode(0, &http(&[(SIGNATURE_HEADER, "00")], body.as_bytes())),
    );
    let inv = InvoiceProvider::new(InvoiceConfig {
        import_token: IMPORT_TOKEN.into(),
        bankgiro: None,
    });
    let number = inv
        .reserve(&req(REFERENCE, Market::Se))
        .expect("an invoice number")
        .id;
    add(
        "pay_callback",
        "ok-invoice-bgmax",
        with_mode(
            2,
            &http(
                &[(IMPORT_TOKEN_HEADER, IMPORT_TOKEN)],
                bgmax_body(&number, 12_500, "20270115").as_bytes(),
            ),
        ),
    );
    add(
        "pay_callback",
        "refused-invoice-no-token",
        with_mode(
            2,
            &http(&[], bgmax_body(&number, 12_500, "20270115").as_bytes()),
        ),
    );

    // feed_config
    let feed = serde_json::json!({
        "vendor.sandbox.acme.wasm": "AGFzbQEAAAA=",
        "vendor.sandbox.acme.toml": "enabled = true\nhttp_hosts = [\"sandbox.invalid\"]\n",
        "monetize.toml": "[policy]\n",
        "fleet": "https://monetize.fuzz.invalid",
        "fleet_instance": INSTANCE,
        "monetize_pubkey": "00",
    });
    add(
        "feed_config",
        "ok-feed-vendor",
        with_mode(0, feed.to_string().as_bytes()),
    );
    add(
        "feed_config",
        "ok-config-empty",
        with_mode(1, b"data_dir = \"/var/lib/monetize\"\n"),
    );
    add(
        "feed_config",
        "refused-config-signup",
        with_mode(1, b"[signup]\nx = 1\n"),
    );

    // signed_facts
    let signer = monetize_signer();
    let snap = signer.sign_snapshot(NOW, vec![signer.sign_fact_at(fact(INSTANCE), NOW)]);
    add(
        "signed_facts",
        "ok-snapshot",
        with_mode(0, &serde_json::to_vec(&snap).unwrap()),
    );
    add(
        "signed_facts",
        "ok-go-ahead",
        with_mode(0, &signer.sign_go_ahead(134_217_728, "n-1", NOW as i64)),
    );
    add(
        "signed_facts",
        "ok-growth",
        with_mode(
            0,
            &signer.sign_estate_growth(
                INSTANCE,
                50,
                (NOW + 86_400_000) as i64,
                REFERENCE,
                NOW as i64,
            ),
        ),
    );
    let unsigned = monetize_embed::signing::Snapshot {
        issued_unix_ms: NOW,
        facts: vec![fact("bob")],
        signature: Vec::new(),
    };
    add(
        "signed_facts",
        "ok-snapshot-harness-signed",
        with_mode(1, &serde_json::to_vec(&unsigned).unwrap()),
    );

    // fleet_door
    add(
        "fleet_door",
        "ok-report",
        with_mode(
            0,
            &signed_call(
                "main",
                "report",
                r#"{"build":"fuzz","measured_unix_ms":1800000000000}"#,
            ),
        ),
    );
    add(
        "fleet_door",
        "ok-orders",
        with_mode(
            0,
            &signed_call("twin", "orders", r#"{"after":0,"wait_ms":0}"#),
        ),
    );
    add(
        "fleet_door",
        "ok-ask-harness-signed",
        with_mode(
            1,
            &signed_call("main", "ask", r#"{"kind":"review_twin","body":{}}"#),
        ),
    );
    add(
        "fleet_door",
        "refused-unsigned",
        with_mode(
            0,
            &monetize_proto::FleetSigned {
                product: PRODUCT.into(),
                instance: INSTANCE.into(),
                role: "main".into(),
                call: "report".into(),
                ..Default::default()
            }
            .encode_to_vec(),
        ),
    );

    // fleet_orders
    let signed = monetize_proto::FleetOrdersAnswer {
        orders: vec![wire_order(
            1,
            "sign_in_again",
            r#"{"account":"acme","to":"a@mock.invalid","host":"acme.fuzz.invalid","ttl_secs":600}"#,
            true,
        )],
    };
    add(
        "fleet_orders",
        "ok-sign-in-again",
        with_mode(0, &signed.encode_to_vec()),
    );
    let unsigned = monetize_proto::FleetOrdersAnswer {
        orders: vec![
            wire_order(
                2,
                "refeed",
                r#"{"keys":{"console_public_site":"on"}}"#,
                false,
            ),
            wire_order(
                3,
                "grow_go_ahead",
                r#"{"go_ahead":"","data_gib":50}"#,
                false,
            ),
        ],
    };
    add(
        "fleet_orders",
        "ok-refeed-harness-signed",
        with_mode(1, &unsigned.encode_to_vec()),
    );
    add(
        "fleet_orders",
        "refused-forged",
        with_mode(0, &unsigned.encode_to_vec()),
    );
    out
}