//! Compiles `proto/monetize/v1/*.proto` into `$OUT_DIR/monetize.v1.rs`.
//!
//! Deliberately protoc-free (pure Rust, nothing shelled out to): `protox` parses the
//! `.proto` sources and hands `tonic-prost-build` a ready `FileDescriptorSet` —
//! the shape `gunnar-ui-server/build.rs` uses, copied. `protox`'s `prost-types`
//! major must equal `tonic-prost-build`'s or `compile_fds` takes a different
//! `FileDescriptorSet` type; the workspace pins both at 0.14 / protox 0.9.
//!
//! Both halves are built: monetize-server implements the server, the console BFF
//! and the CLI consume the client.
use std::path::PathBuf;
const PROTOS: &[&str] = &[
"common.proto",
"entitlement.proto",
"purchase.proto",
"usage.proto",
"products.proto",
"ledger.proto",
"events.proto",
// The paid-signup seam: the return page's one poll, and the operator's list.
"signup.proto",
"signup_admin.proto",
// The TAX RETURN seam: the periods a year is filed in, and one filled form.
"tax.proto",
// The refused vendor callbacks: the operator's read of the bounded ring a
// failed delivery now leaves a row in.
"callback_admin.proto",
// What the VENDOR says it took and monetize did not fulfil: the
// reconciler's durable rows, the operator's read of them.
"reconcile_admin.proto",
// The data-set growth: the OUTSIDE actor's console — status, quote,
// approve, resume (`DATA-SET-GROWTH-FLOW.md` T6).
"grow_admin.proto",
// The estate, drawn: one board, one chip per machine. The picture crosses
// the wire because only monetize-server holds both halves it is drawn from.
"estate.proto",
// A private gunnar, ordered: the order page's two calls over the
// lay-estate job (`monetize_server::estate_order`).
"estate_order.proto",
// ONE monetize: every (product, tenant) account and the rows on it — the
// subscription, the purchases, the private instances it owns.
"accounts.proto",
// The pull channel (5.4): estates report, pull signed orders and ask; and
// the guardian's console (cases, the buttons, the auto-fix opt-in).
"fleet.proto",
// The operator's TEST BUTTON (2026-10-11): each product's declared test
// actions, run through the same sign-up / estate-order path a customer takes.
"test_purchase.proto",
// The operator's SITE BOOK (2026-10-14): a site added and edited in the application,
// judged by the box's own loader, applied live, audited.
"site_book.proto",
// The ONE box's PLUGINS (2026-10-17): the release's signed plugin list taken from the
// release bucket, verified before a byte is written, swapped live by the guest watcher.
"plugins.proto",
// The ESTATES that exist and the NEW-ESTATE slot (2026-10-29, lane OVW-CLEAN): the console's
// Overview, classified by the server; a new estate handed to the one site order.
"estates.proto",
];
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Read when the script RUNS, not when it was compiled: the target dir is
// shared across checkouts, and a script compiled in another one kept that
// checkout's path baked in and failed here with "not in any include path".
let include = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR")?).join("proto");
let files: Vec<PathBuf> = PROTOS.iter().map(|f| include.join("monetize/v1").join(f)).collect();
for file in &files {
println!("cargo:rerun-if-changed={}", file.display());
}
let descriptors = protox::compile(&files, [&include])?;
tonic_prost_build::configure()
.build_server(true)
.build_client(true)
// `default-stubs` (test fakes only): every server method gets tonic's UNIMPLEMENTED
// body, so a fake writes only what its test calls. A real server never names it.
.generate_default_stubs(std::env::var_os("CARGO_FEATURE_DEFAULT_STUBS").is_some())
// Every `map<>` as a BTreeMap: the Rust contracts use BTreeMap, so the caps
// convert without a copy and serialize in one stable order.
.btree_map(".")
// Nothing on this path needs protoc; a stray PROTOC in the environment must
// not change the outcome.
.skip_protoc_run()
.compile_fds(descriptors)?;
Ok(())
}