use std::collections::{BTreeMap, BTreeSet};
use std::fmt;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use gateway_core::catalog::ModelPrice;
use super::canonical::{Canonical, CanonicalError, CanonicalValue, Checksum, InvalidChecksum};
use super::ids::{ResourceId, Slug};
use super::mutation::{Actor, InvalidActor};
use super::record::{BodyError, DisplayNameError, Record, SCHEMA_FIELD};
use super::resource::{
ResourceBody, ResourceKind, ResourceRef, ResourceScope, ResourceVersion, ResourceVersionNumber,
};
use super::revision::DesiredState;
use super::tenancy::{DisplayName, InvalidDisplayName};
use crate::backends::catalog::{
CatalogContentId, InvalidCatalogId, JsonPointer, ObservedRate, ProviderId,
};
pub const PRICE_BOOK_SCHEMA: &str = "axond.price-book.v1";
const CATALOG_FIELD: &str = "catalog_content_id";
const CURRENCY_FIELD: &str = "currency";
const UNIT_FIELD: &str = "unit";
const APPROVAL_FIELD: &str = "approval";
const RULES_FIELD: &str = "rules";
const PROVIDER_FIELD: &str = "provider";
const MODEL_FIELD: &str = "published_model_id";
const PRECEDENCE_FIELD: &str = "precedence";
const FROM_FIELD: &str = "effective_from";
const UNTIL_FIELD: &str = "effective_until";
const RATES_FIELD: &str = "rates";
const TIERS_FIELD: &str = "tiers";
const PROVENANCE_FIELD: &str = "provenance";
const STATE_FIELD: &str = "state";
const APPROVED_BY_FIELD: &str = "by";
const APPROVED_AT_FIELD: &str = "at";
const CITATION_FIELD: &str = "citation";
const ORIGIN_FIELD: &str = "origin";
const POINTER_FIELD: &str = "pointer";
const INPUT_FIELD: &str = "input";
const OUTPUT_FIELD: &str = "output";
const REASONING_FIELD: &str = "reasoning";
const CACHE_READ_FIELD: &str = "cache_read";
const CACHE_WRITE_FIELD: &str = "cache_write";
const INPUT_AUDIO_FIELD: &str = "input_audio";
const OUTPUT_AUDIO_FIELD: &str = "output_audio";
const THRESHOLD_FIELD: &str = "threshold";
const TYPE_FIELD: &str = "type";
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum Currency {
#[default]
Usd,
}
impl Currency {
pub const ALL: &'static [Self] = &[Self::Usd];
pub const fn as_str(self) -> &'static str {
match self {
Self::Usd => "USD",
}
}
fn parse(text: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|it| it.as_str() == text)
}
}
impl fmt::Display for Currency {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
pub enum RateUnit {
#[default]
NanoDollarsPerMillionTokens,
}
impl RateUnit {
pub const ALL: &'static [Self] = &[Self::NanoDollarsPerMillionTokens];
pub const fn as_str(self) -> &'static str {
match self {
Self::NanoDollarsPerMillionTokens => "nano-dollars-per-million-tokens",
}
}
fn parse(text: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|it| it.as_str() == text)
}
}
impl fmt::Display for RateUnit {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ApprovedRate(u64);
impl ApprovedRate {
pub const ZERO: Self = Self(0);
pub const fn from_nanos(nanos: u64) -> Self {
Self(nanos)
}
pub const fn approving(observed: ObservedRate) -> Self {
Self(observed.nanos())
}
pub const fn nanos(self) -> u64 {
self.0
}
fn micro_dollars(self, field: &'static str) -> Result<u64, RateRejection> {
const PER_MICRO: u64 = 1_000;
if self.0.is_multiple_of(PER_MICRO) {
Ok(self.0 / PER_MICRO)
} else {
Err(RateRejection::ExcessPrecision {
field,
nanos: self.0,
})
}
}
}
impl fmt::Display for ApprovedRate {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{} nano-dollars/Mtok", self.0)
}
}
impl Canonical for ApprovedRate {
fn canonical(&self) -> CanonicalValue {
CanonicalValue::integer(self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum RateRejection {
#[error("rate `{field}` is negative ({value})")]
Negative { field: &'static str, value: i128 },
#[error(
"rate `{field}` of {nanos} nano-dollars/Mtok is finer than the micro-dollar the runtime \
bills in; approve a rate that is a whole number of micro-dollars rather than one that \
would have to be rounded"
)]
ExcessPrecision { field: &'static str, nanos: u64 },
#[error("rate `{field}` of {value} does not fit an unsigned 64-bit nano-dollar rate")]
Overflow { field: &'static str, value: i128 },
#[error(
"a `{threshold}` price tier cannot be approved: the request path applies one rate \
schedule per target and would bill the base rate regardless"
)]
UnsupportedTier { threshold: String },
#[error(
"rate `{field}` cannot be approved: the gateway's usage record has no matching token \
count, so a request would never be billed for it"
)]
UnbillableUsage { field: &'static str },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ApprovedRates {
pub input: ApprovedRate,
pub output: ApprovedRate,
pub reasoning: Option<ApprovedRate>,
pub cache_read: Option<ApprovedRate>,
pub cache_write: Option<ApprovedRate>,
pub input_audio: Option<ApprovedRate>,
pub output_audio: Option<ApprovedRate>,
}
impl ApprovedRates {
pub const fn new(input: ApprovedRate, output: ApprovedRate) -> Self {
Self {
input,
output,
reasoning: None,
cache_read: None,
cache_write: None,
input_audio: None,
output_audio: None,
}
}
pub fn to_model_price(self) -> Result<ModelPrice, RateRejection> {
if self.input_audio.is_some() {
return Err(RateRejection::UnbillableUsage {
field: INPUT_AUDIO_FIELD,
});
}
if self.output_audio.is_some() {
return Err(RateRejection::UnbillableUsage {
field: OUTPUT_AUDIO_FIELD,
});
}
let optional = |rate: Option<ApprovedRate>, field| {
rate.map(|rate| rate.micro_dollars(field)).transpose()
};
Ok(ModelPrice {
input_microdollars_per_million: self.input.micro_dollars(INPUT_FIELD)?,
output_microdollars_per_million: self.output.micro_dollars(OUTPUT_FIELD)?,
reasoning_microdollars_per_million: optional(self.reasoning, REASONING_FIELD)?,
cache_read_microdollars_per_million: optional(self.cache_read, CACHE_READ_FIELD)?,
cache_write_microdollars_per_million: optional(self.cache_write, CACHE_WRITE_FIELD)?,
})
}
}
impl Canonical for ApprovedRates {
fn canonical(&self) -> CanonicalValue {
let mut fields = vec![
(INPUT_FIELD.to_owned(), self.input.canonical()),
(OUTPUT_FIELD.to_owned(), self.output.canonical()),
];
for (field, rate) in [
(REASONING_FIELD, self.reasoning),
(CACHE_READ_FIELD, self.cache_read),
(CACHE_WRITE_FIELD, self.cache_write),
(INPUT_AUDIO_FIELD, self.input_audio),
(OUTPUT_AUDIO_FIELD, self.output_audio),
] {
if let Some(rate) = rate {
fields.push((field.to_owned(), rate.canonical()));
}
}
CanonicalValue::map(fields)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EffectiveInstant(u64);
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum InvalidInstant {
#[error("an effective instant cannot precede the Unix epoch")]
BeforeEpoch,
#[error("{millis} milliseconds since the epoch does not fit an unsigned 64-bit instant")]
Overflow { millis: u128 },
}
impl EffectiveInstant {
pub const EPOCH: Self = Self(0);
pub const fn from_millis(millis: u64) -> Self {
Self(millis)
}
pub const fn millis(self) -> u64 {
self.0
}
pub fn of(time: SystemTime) -> Result<Self, InvalidInstant> {
let millis = time
.duration_since(UNIX_EPOCH)
.map_err(|_| InvalidInstant::BeforeEpoch)?
.as_millis();
u64::try_from(millis)
.map(Self)
.map_err(|_| InvalidInstant::Overflow { millis })
}
pub fn to_system_time(self) -> Option<SystemTime> {
UNIX_EPOCH.checked_add(Duration::from_millis(self.0))
}
}
impl fmt::Display for EffectiveInstant {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}ms", self.0)
}
}
impl Canonical for EffectiveInstant {
fn canonical(&self) -> CanonicalValue {
CanonicalValue::integer(self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum InvalidInterval {
#[error("an effective interval ending at {until} cannot begin at {from}")]
Empty {
from: EffectiveInstant,
until: EffectiveInstant,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct EffectiveInterval {
from: EffectiveInstant,
until: Option<EffectiveInstant>,
}
impl EffectiveInterval {
pub const fn from(from: EffectiveInstant) -> Self {
Self { from, until: None }
}
pub const fn bounded(
from: EffectiveInstant,
until: EffectiveInstant,
) -> Result<Self, InvalidInterval> {
if until.0 <= from.0 {
return Err(InvalidInterval::Empty { from, until });
}
Ok(Self {
from,
until: Some(until),
})
}
pub const fn starts(self) -> EffectiveInstant {
self.from
}
pub const fn ends(self) -> Option<EffectiveInstant> {
self.until
}
pub const fn contains(self, at: EffectiveInstant) -> bool {
if at.0 < self.from.0 {
return false;
}
match self.until {
None => true,
Some(until) => at.0 < until.0,
}
}
pub const fn overlaps(self, other: Self) -> bool {
let starts_before_other_ends = match other.until {
None => true,
Some(until) => self.from.0 < until.0,
};
let other_starts_before_self_ends = match self.until {
None => true,
Some(until) => other.from.0 < until.0,
};
starts_before_other_ends && other_starts_before_self_ends
}
}
impl fmt::Display for EffectiveInterval {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self.until {
None => write!(f, "[{}, ∞)", self.from),
Some(until) => write!(f, "[{}, {until})", self.from),
}
}
}
impl Canonical for EffectiveInterval {
fn canonical(&self) -> CanonicalValue {
let mut fields = vec![(FROM_FIELD.to_owned(), self.from.canonical())];
if let Some(until) = self.until {
fields.push((UNTIL_FIELD.to_owned(), until.canonical()));
}
CanonicalValue::map(fields)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum RulePrecedence {
Baseline,
Override,
}
impl RulePrecedence {
pub const ALL: &'static [Self] = &[Self::Baseline, Self::Override];
pub const fn as_str(self) -> &'static str {
match self {
Self::Baseline => "baseline",
Self::Override => "override",
}
}
fn parse(text: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|it| it.as_str() == text)
}
}
impl fmt::Display for RulePrecedence {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct PricedTarget {
pub provider: ProviderId,
pub published_model_id: String,
}
impl PricedTarget {
pub fn new(provider: ProviderId, published_model_id: impl Into<String>) -> Self {
Self {
provider,
published_model_id: published_model_id.into(),
}
}
}
impl fmt::Display for PricedTarget {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}/{}", self.provider.as_str(), self.published_model_id)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum PriceOrigin {
Catalogue,
Negotiated,
Operator,
}
impl PriceOrigin {
pub const ALL: &'static [Self] = &[Self::Catalogue, Self::Negotiated, Self::Operator];
pub const fn as_str(self) -> &'static str {
match self {
Self::Catalogue => "catalogue",
Self::Negotiated => "negotiated",
Self::Operator => "operator",
}
}
fn parse(text: &str) -> Option<Self> {
Self::ALL.iter().copied().find(|it| it.as_str() == text)
}
}
impl fmt::Display for PriceOrigin {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(self.as_str())
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PriceProvenance {
pub origin: PriceOrigin,
pub pointer: Option<JsonPointer>,
pub citation: Option<DisplayName>,
}
impl PriceProvenance {
pub const fn stated(origin: PriceOrigin) -> Self {
Self {
origin,
pointer: None,
citation: None,
}
}
pub fn cited(origin: PriceOrigin, citation: DisplayName) -> Self {
Self {
origin,
pointer: None,
citation: Some(citation),
}
}
}
impl Canonical for PriceProvenance {
fn canonical(&self) -> CanonicalValue {
let mut fields = vec![(
ORIGIN_FIELD.to_owned(),
CanonicalValue::string(self.origin.as_str()),
)];
if let Some(pointer) = &self.pointer {
fields.push((POINTER_FIELD.to_owned(), pointer.canonical()));
}
if let Some(citation) = &self.citation {
fields.push((
CITATION_FIELD.to_owned(),
CanonicalValue::string(citation.as_str()),
));
}
CanonicalValue::map(fields)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Approval {
Draft,
Approved {
by: Actor,
at: EffectiveInstant,
citation: Option<DisplayName>,
},
}
impl Approval {
pub const fn is_approved(&self) -> bool {
matches!(self, Self::Approved { .. })
}
pub const fn state(&self) -> &'static str {
match self {
Self::Draft => "draft",
Self::Approved { .. } => "approved",
}
}
pub const fn approver(&self) -> Option<&Actor> {
match self {
Self::Draft => None,
Self::Approved { by, .. } => Some(by),
}
}
}
impl Canonical for Approval {
fn canonical(&self) -> CanonicalValue {
match self {
Self::Draft => {
CanonicalValue::map([(STATE_FIELD, CanonicalValue::string(Self::Draft.state()))])
}
Self::Approved { by, at, citation } => {
let mut fields = vec![
(STATE_FIELD.to_owned(), CanonicalValue::string(self.state())),
(APPROVED_BY_FIELD.to_owned(), by.canonical()),
(APPROVED_AT_FIELD.to_owned(), at.canonical()),
];
if let Some(citation) = citation {
fields.push((
CITATION_FIELD.to_owned(),
CanonicalValue::string(citation.as_str()),
));
}
CanonicalValue::map(fields)
}
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PriceRule {
target: PricedTarget,
precedence: RulePrecedence,
effective: EffectiveInterval,
rates: ApprovedRates,
price: ModelPrice,
provenance: PriceProvenance,
}
impl PriceRule {
pub fn new(
target: PricedTarget,
precedence: RulePrecedence,
effective: EffectiveInterval,
rates: ApprovedRates,
provenance: PriceProvenance,
) -> Result<Self, RateRejection> {
Ok(Self {
target,
precedence,
effective,
rates,
price: rates.to_model_price()?,
provenance,
})
}
pub const fn target(&self) -> &PricedTarget {
&self.target
}
pub const fn precedence(&self) -> RulePrecedence {
self.precedence
}
pub const fn effective(&self) -> EffectiveInterval {
self.effective
}
pub const fn rates(&self) -> ApprovedRates {
self.rates
}
pub const fn price(&self) -> ModelPrice {
self.price
}
pub const fn provenance(&self) -> &PriceProvenance {
&self.provenance
}
}
impl Canonical for PriceRule {
fn canonical(&self) -> CanonicalValue {
let mut fields = vec![
(PROVIDER_FIELD.to_owned(), self.target.provider.canonical()),
(
MODEL_FIELD.to_owned(),
CanonicalValue::string(&self.target.published_model_id),
),
(
PRECEDENCE_FIELD.to_owned(),
CanonicalValue::string(self.precedence.as_str()),
),
(FROM_FIELD.to_owned(), self.effective.from.canonical()),
(RATES_FIELD.to_owned(), self.rates.canonical()),
(PROVENANCE_FIELD.to_owned(), self.provenance.canonical()),
];
if let Some(until) = self.effective.until {
fields.push((UNTIL_FIELD.to_owned(), until.canonical()));
}
CanonicalValue::map(fields)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PriceBookBody {
catalog: CatalogContentId,
currency: Currency,
unit: RateUnit,
approval: Approval,
rules: Vec<PriceRule>,
}
impl PriceBookBody {
pub const SCHEMA: &'static str = PRICE_BOOK_SCHEMA;
const KNOWN_FIELDS: &'static [&'static str] = &[
CATALOG_FIELD,
CURRENCY_FIELD,
UNIT_FIELD,
APPROVAL_FIELD,
RULES_FIELD,
];
const RULE_FIELDS: &'static [&'static str] = &[
PROVIDER_FIELD,
MODEL_FIELD,
PRECEDENCE_FIELD,
FROM_FIELD,
UNTIL_FIELD,
RATES_FIELD,
TIERS_FIELD,
PROVENANCE_FIELD,
];
const RATE_FIELDS: &'static [&'static str] = &[
INPUT_FIELD,
OUTPUT_FIELD,
REASONING_FIELD,
CACHE_READ_FIELD,
CACHE_WRITE_FIELD,
INPUT_AUDIO_FIELD,
OUTPUT_AUDIO_FIELD,
];
const APPROVAL_FIELDS: &'static [&'static str] = &[
STATE_FIELD,
APPROVED_BY_FIELD,
APPROVED_AT_FIELD,
CITATION_FIELD,
];
const PROVENANCE_FIELDS: &'static [&'static str] =
&[ORIGIN_FIELD, POINTER_FIELD, CITATION_FIELD];
pub const fn new(catalog: CatalogContentId, approval: Approval) -> Self {
Self {
catalog,
currency: Currency::Usd,
unit: RateUnit::NanoDollarsPerMillionTokens,
approval,
rules: Vec::new(),
}
}
#[must_use]
pub fn with_rule(mut self, rule: PriceRule) -> Self {
self.rules.push(rule);
self
}
pub const fn catalog(&self) -> CatalogContentId {
self.catalog
}
pub const fn currency(&self) -> Currency {
self.currency
}
pub const fn unit(&self) -> RateUnit {
self.unit
}
pub const fn approval(&self) -> &Approval {
&self.approval
}
pub fn rules(&self) -> &[PriceRule] {
&self.rules
}
pub fn body(&self) -> ResourceBody {
ResourceBody::Inline(self.canonical())
}
pub fn version(&self, id: ResourceId, slug: Slug) -> ResourceVersion {
self.version_at(id, slug, ResourceVersionNumber::FIRST)
}
pub fn version_at(
&self,
id: ResourceId,
slug: Slug,
version: ResourceVersionNumber,
) -> ResourceVersion {
ResourceVersion::new(
ResourceRef::new(ResourceKind::Price, id, version),
ResourceScope::Deployment,
slug,
self.body(),
)
}
pub fn read(resource: &ResourceVersion) -> Result<Self, PricingError> {
let record = Record::<PricingError>::open(
resource,
ResourceKind::Price,
Self::SCHEMA,
Self::KNOWN_FIELDS,
)?;
let reference = resource.reference;
let catalog = record.string(CATALOG_FIELD)?;
let catalog =
Checksum::parse(catalog).map_err(|source| PricingError::MalformedChecksum {
reference,
field: CATALOG_FIELD,
source,
})?;
let currency = record.string(CURRENCY_FIELD)?;
let currency = Currency::parse(currency).ok_or_else(|| PricingError::UnknownCurrency {
reference,
currency: currency.to_owned(),
})?;
let unit = record.string(UNIT_FIELD)?;
let unit = RateUnit::parse(unit).ok_or_else(|| PricingError::UnknownUnit {
reference,
unit: unit.to_owned(),
})?;
let approval = record.record(Self::SCHEMA, APPROVAL_FIELD, Self::APPROVAL_FIELDS)?;
let approval = Self::read_approval(&approval)?;
let mut rules = Vec::new();
for member in record.set(RULES_FIELD)? {
let rule = Record::nested(
reference,
Self::SCHEMA,
RULES_FIELD,
member,
Self::RULE_FIELDS,
)?;
rules.push(Self::read_rule(&rule)?);
}
let book = Self {
catalog: CatalogContentId::from_checksum(catalog),
currency,
unit,
approval,
rules,
};
book.check_rule_consistency(reference)?;
Ok(book)
}
fn read_approval(record: &Record<'_, PricingError>) -> Result<Approval, PricingError> {
match record.string(STATE_FIELD)? {
"draft" => {
for field in [APPROVED_BY_FIELD, APPROVED_AT_FIELD, CITATION_FIELD] {
if record.optional_value(field).is_some() {
return Err(PricingError::UnknownField {
reference: record.reference(),
schema: PRICE_BOOK_SCHEMA,
field: field.to_owned(),
});
}
}
Ok(Approval::Draft)
}
"approved" => Ok(Approval::Approved {
by: record.actor(APPROVED_BY_FIELD)?,
at: record.instant(APPROVED_AT_FIELD)?,
citation: record.optional_display_name(CITATION_FIELD)?,
}),
state => Err(PricingError::UnknownApprovalState {
reference: record.reference(),
state: state.to_owned(),
}),
}
}
fn read_rule(record: &Record<'_, PricingError>) -> Result<PriceRule, PricingError> {
let reference = record.reference();
let provider = record.catalog_id(PROVIDER_FIELD)?;
let published_model_id = record.string(MODEL_FIELD)?.to_owned();
let target = PricedTarget {
provider,
published_model_id,
};
let precedence = record.string(PRECEDENCE_FIELD)?;
let precedence =
RulePrecedence::parse(precedence).ok_or_else(|| PricingError::UnknownPrecedence {
reference,
precedence: precedence.to_owned(),
})?;
let from = record.instant(FROM_FIELD)?;
let effective = match record.optional_instant(UNTIL_FIELD)? {
None => EffectiveInterval::from(from),
Some(until) => EffectiveInterval::bounded(from, until).map_err(|source| {
PricingError::InvalidInterval {
reference,
target: target.to_string(),
source,
}
})?,
};
record
.reject_tiers(TIERS_FIELD)
.map_err(|source| PricingError::Rate {
reference,
target: target.to_string(),
source,
})?;
let rates = record.record(Self::SCHEMA, RATES_FIELD, Self::RATE_FIELDS)?;
let rates = ApprovedRates {
input: rates.rate(&target, INPUT_FIELD)?,
output: rates.rate(&target, OUTPUT_FIELD)?,
reasoning: rates.optional_rate(&target, REASONING_FIELD)?,
cache_read: rates.optional_rate(&target, CACHE_READ_FIELD)?,
cache_write: rates.optional_rate(&target, CACHE_WRITE_FIELD)?,
input_audio: rates.optional_rate(&target, INPUT_AUDIO_FIELD)?,
output_audio: rates.optional_rate(&target, OUTPUT_AUDIO_FIELD)?,
};
let provenance = record.record(Self::SCHEMA, PROVENANCE_FIELD, Self::PROVENANCE_FIELDS)?;
let origin = provenance.string(ORIGIN_FIELD)?;
let provenance = PriceProvenance {
origin: PriceOrigin::parse(origin).ok_or_else(|| PricingError::UnknownOrigin {
reference,
origin: origin.to_owned(),
})?,
pointer: provenance
.optional_string(POINTER_FIELD)?
.map(JsonPointer::new),
citation: provenance.optional_display_name(CITATION_FIELD)?,
};
PriceRule::new(target.clone(), precedence, effective, rates, provenance).map_err(|source| {
PricingError::Rate {
reference,
target: target.to_string(),
source,
}
})
}
fn check_rule_consistency(&self, reference: ResourceRef) -> Result<(), PricingError> {
let mut by_key: BTreeMap<(&PricedTarget, RulePrecedence), Vec<&PriceRule>> =
BTreeMap::new();
for rule in &self.rules {
by_key
.entry((&rule.target, rule.precedence))
.or_default()
.push(rule);
}
for ((target, precedence), mut rules) in by_key {
rules.sort_by_key(|rule| rule.effective);
for pair in rules.windows(2) {
if pair[0].effective.overlaps(pair[1].effective) {
return Err(PricingError::OverlappingRules {
reference,
target: target.to_string(),
precedence,
first: pair[0].effective,
second: pair[1].effective,
});
}
}
}
Ok(())
}
fn boundaries(&self) -> BTreeSet<EffectiveInstant> {
let mut boundaries = BTreeSet::new();
for rule in &self.rules {
boundaries.insert(rule.effective.from);
if let Some(until) = rule.effective.until {
boundaries.insert(until);
}
}
boundaries
}
fn stable_interval(&self, at: EffectiveInstant) -> EffectiveInterval {
let boundaries = self.boundaries();
let from = boundaries
.range(..=at)
.next_back()
.copied()
.unwrap_or(EffectiveInstant::EPOCH);
match boundaries
.range(EffectiveInstant(at.0.saturating_add(1))..)
.next()
.copied()
.filter(|until| until.0 > from.0)
{
None => EffectiveInterval::from(from),
Some(until) => EffectiveInterval::bounded(from, until)
.expect("a boundary after `at` is after the boundary at or before it"),
}
}
fn in_force(&self, at: EffectiveInstant) -> BTreeMap<&PricedTarget, &PriceRule> {
let mut resolved: BTreeMap<&PricedTarget, &PriceRule> = BTreeMap::new();
for rule in &self.rules {
if !rule.effective.contains(at) {
continue;
}
resolved
.entry(&rule.target)
.and_modify(|winner| {
if rule.precedence > winner.precedence {
*winner = rule;
}
})
.or_insert(rule);
}
resolved
}
}
impl Canonical for PriceBookBody {
fn canonical(&self) -> CanonicalValue {
CanonicalValue::map([
(SCHEMA_FIELD, CanonicalValue::string(Self::SCHEMA)),
(
CATALOG_FIELD,
CanonicalValue::string(self.catalog.checksum().to_string()),
),
(
CURRENCY_FIELD,
CanonicalValue::string(self.currency.as_str()),
),
(UNIT_FIELD, CanonicalValue::string(self.unit.as_str())),
(APPROVAL_FIELD, self.approval.canonical()),
(
RULES_FIELD,
CanonicalValue::set(self.rules.iter().map(Canonical::canonical)),
),
])
}
}
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum PricingError {
#[error("{reference} is a {} resource, not a {}", found.as_str(), expected.as_str())]
Kind {
reference: ResourceRef,
expected: ResourceKind,
found: ResourceKind,
},
#[error(
"{reference} carries a {scope:?}-scoped price book; this build approves pricing for the \
deployment as a whole, and a tenant-scoped price book would change which budget a \
request is charged against without the routing model representing it"
)]
ScopeNotSupported {
reference: ResourceRef,
scope: ResourceScope,
},
#[error(
"{first} and {second} are both deployment price books; one deployment has one approved \
baseline, so which of two applies would be undefined"
)]
MultipleBooks {
first: ResourceRef,
second: ResourceRef,
},
#[error("{reference} does not carry an inline body")]
NotInline { reference: ResourceRef },
#[error("{reference} does not carry a record")]
NotARecord { reference: ResourceRef },
#[error("{reference} carries a body no canonical writer could have produced: {source}")]
Uncanonicalizable {
reference: ResourceRef,
#[source]
source: CanonicalError,
},
#[error("{reference} declares schema `{found}`, not `{expected}`")]
Schema {
reference: ResourceRef,
expected: &'static str,
found: String,
},
#[error(
"{reference} carries a `schema` that is not an identifier, which no release wrote; \
restore the row or republish the resource rather than changing build"
)]
DamagedSchema { reference: ResourceRef },
#[error("{reference} is missing the `{field}` field")]
MissingField {
reference: ResourceRef,
field: &'static str,
},
#[error("{reference} carries the field `{field}`, which `{schema}` does not define")]
UnknownField {
reference: ResourceRef,
schema: &'static str,
field: String,
},
#[error("{reference} field `{field}` is not the type `{schema}` defines")]
FieldType {
reference: ResourceRef,
schema: &'static str,
field: &'static str,
},
#[error("{reference} field `{field}` is not a checksum: {source}")]
MalformedChecksum {
reference: ResourceRef,
field: &'static str,
#[source]
source: InvalidChecksum,
},
#[error("{reference} field `{field}` is not a catalogue identifier: {source}")]
MalformedId {
reference: ResourceRef,
field: &'static str,
#[source]
source: InvalidCatalogId,
},
#[error("{reference} field `{field}` is not an operator-facing name: {source}")]
MalformedCitation {
reference: ResourceRef,
field: &'static str,
#[source]
source: InvalidDisplayName,
},
#[error("{reference} field `{field}` does not record an actor: {source}")]
MalformedActor {
reference: ResourceRef,
field: &'static str,
#[source]
source: InvalidActor,
},
#[error("{reference} states its rates in `{currency}`, which this build does not bill in")]
UnknownCurrency {
reference: ResourceRef,
currency: String,
},
#[error("{reference} states its rates in `{unit}`, which this build cannot convert")]
UnknownUnit {
reference: ResourceRef,
unit: String,
},
#[error("{reference} records approval state `{state}`, which this build does not know")]
UnknownApprovalState {
reference: ResourceRef,
state: String,
},
#[error("{reference} records rule precedence `{precedence}`, which this build does not know")]
UnknownPrecedence {
reference: ResourceRef,
precedence: String,
},
#[error("{reference} records price origin `{origin}`, which this build does not know")]
UnknownOrigin {
reference: ResourceRef,
origin: String,
},
#[error("{reference} field `{field}` is not an instant on the effective-dating timeline")]
MalformedInstant {
reference: ResourceRef,
field: &'static str,
},
#[error("{reference} dates the rule for {target} over an interval that is empty: {source}")]
InvalidInterval {
reference: ResourceRef,
target: String,
#[source]
source: InvalidInterval,
},
#[error("{reference} cannot bill the approved rate for {target}: {source}")]
Rate {
reference: ResourceRef,
target: String,
#[source]
source: RateRejection,
},
#[error(
"{reference} states two {precedence} rules for {target} that are both in force — {first} \
and {second} — so which rate applies would be undefined; use an `override` rule to \
supersede a baseline"
)]
OverlappingRules {
reference: ResourceRef,
target: String,
precedence: RulePrecedence,
first: EffectiveInterval,
second: EffectiveInterval,
},
}
impl PricingError {
pub const fn reference(&self) -> ResourceRef {
match self {
Self::Kind { reference, .. }
| Self::ScopeNotSupported { reference, .. }
| Self::MultipleBooks {
second: reference, ..
}
| Self::NotInline { reference }
| Self::NotARecord { reference }
| Self::Uncanonicalizable { reference, .. }
| Self::Schema { reference, .. }
| Self::DamagedSchema { reference }
| Self::MissingField { reference, .. }
| Self::UnknownField { reference, .. }
| Self::FieldType { reference, .. }
| Self::MalformedChecksum { reference, .. }
| Self::MalformedId { reference, .. }
| Self::MalformedCitation { reference, .. }
| Self::MalformedActor { reference, .. }
| Self::UnknownCurrency { reference, .. }
| Self::UnknownUnit { reference, .. }
| Self::UnknownApprovalState { reference, .. }
| Self::UnknownPrecedence { reference, .. }
| Self::UnknownOrigin { reference, .. }
| Self::MalformedInstant { reference, .. }
| Self::InvalidInterval { reference, .. }
| Self::Rate { reference, .. }
| Self::OverlappingRules { reference, .. } => *reference,
}
}
pub fn is_incompatible(&self) -> bool {
if let Self::MissingField { field, .. } = self {
return *field == SCHEMA_FIELD;
}
matches!(
self,
Self::Schema { .. }
| Self::UnknownField { .. }
| Self::UnknownCurrency { .. }
| Self::UnknownUnit { .. }
| Self::UnknownApprovalState { .. }
| Self::UnknownPrecedence { .. }
| Self::UnknownOrigin { .. }
| Self::MalformedCitation { .. }
| Self::MalformedActor {
source: InvalidActor::UnknownKind { .. } | InvalidActor::UnknownField { .. },
..
}
| Self::Rate {
source: RateRejection::ExcessPrecision { .. }
| RateRejection::UnsupportedTier { .. }
| RateRejection::UnbillableUsage { .. },
..
}
| Self::ScopeNotSupported { .. }
)
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PriceBook {
pub reference: ResourceRef,
pub slug: Slug,
pub body: PriceBookBody,
pub checksum: Checksum,
}
fn declares_a_price_book(resource: &ResourceVersion) -> bool {
let ResourceBody::Inline(CanonicalValue::Map(fields)) = &resource.body else {
return false;
};
fields.iter().any(|(field, value)| {
field == SCHEMA_FIELD && *value == CanonicalValue::string(PRICE_BOOK_SCHEMA)
})
}
fn carries_a_damaged_schema(resource: &ResourceVersion) -> bool {
let ResourceBody::Inline(CanonicalValue::Map(fields)) = &resource.body else {
return false;
};
fields
.iter()
.any(|(field, value)| field == SCHEMA_FIELD && !matches!(value, CanonicalValue::String(_)))
}
#[derive(Debug, Clone, PartialEq, Eq, Default)]
pub struct PriceBooks {
book: Option<PriceBook>,
}
impl PriceBooks {
pub fn of(state: &DesiredState) -> Result<Self, PricingError> {
let mut books = Self::default();
for resource in state.resources() {
if resource.reference.kind != ResourceKind::Price {
continue;
}
if resource.scope != ResourceScope::Deployment && !declares_a_price_book(resource) {
if carries_a_damaged_schema(resource) {
return Err(PricingError::DamagedSchema {
reference: resource.reference,
});
}
continue;
}
if let Some(first) = &books.book {
return Err(PricingError::MultipleBooks {
first: first.reference,
second: resource.reference,
});
}
if resource.scope != ResourceScope::Deployment {
return Err(PricingError::ScopeNotSupported {
reference: resource.reference,
scope: resource.scope.clone(),
});
}
let body = PriceBookBody::read(resource)?;
let ResourceBody::Inline(stored) = &resource.body else {
return Err(PricingError::NotInline {
reference: resource.reference,
});
};
let checksum = stored
.checksum()
.map_err(|source| PricingError::Uncanonicalizable {
reference: resource.reference,
source,
})?;
books.book = Some(PriceBook {
reference: resource.reference,
slug: resource.slug.clone(),
body,
checksum,
});
}
Ok(books)
}
pub const fn book(&self) -> Option<&PriceBook> {
self.book.as_ref()
}
pub fn snapshot_at(&self, at: EffectiveInstant) -> Option<PricingSnapshot> {
self.book.as_ref().map(|book| PricingSnapshot::of(book, at))
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct PricingSnapshot {
book: ResourceRef,
checksum: Checksum,
catalog: CatalogContentId,
approval: Approval,
effective: EffectiveInterval,
targets: BTreeMap<PricedTarget, ModelPrice>,
}
impl PricingSnapshot {
pub fn of(book: &PriceBook, at: EffectiveInstant) -> Self {
let targets = if book.body.approval.is_approved() {
book.body
.in_force(at)
.into_iter()
.map(|(target, rule)| (target.clone(), rule.price()))
.collect()
} else {
BTreeMap::new()
};
Self {
book: book.reference,
checksum: book.checksum,
catalog: book.body.catalog(),
approval: book.body.approval.clone(),
effective: book.body.stable_interval(at),
targets,
}
}
pub const fn book(&self) -> ResourceRef {
self.book
}
pub const fn checksum(&self) -> Checksum {
self.checksum
}
pub const fn catalog(&self) -> CatalogContentId {
self.catalog
}
pub const fn approval(&self) -> &Approval {
&self.approval
}
pub const fn is_approved(&self) -> bool {
self.approval.is_approved()
}
pub const fn effective(&self) -> EffectiveInterval {
self.effective
}
pub fn price(&self, provider: &ProviderId, published_model_id: &str) -> Option<ModelPrice> {
self.targets
.iter()
.find(|(target, _)| {
target.provider == *provider && target.published_model_id == published_model_id
})
.map(|(_, price)| *price)
}
pub fn targets(&self) -> impl ExactSizeIterator<Item = (&PricedTarget, &ModelPrice)> {
self.targets.iter()
}
pub fn is_empty(&self) -> bool {
self.targets.is_empty()
}
}
impl BodyError for PricingError {
fn kind(reference: ResourceRef, expected: ResourceKind, found: ResourceKind) -> Self {
Self::Kind {
reference,
expected,
found,
}
}
fn not_inline(reference: ResourceRef) -> Self {
Self::NotInline { reference }
}
fn not_a_record(reference: ResourceRef) -> Self {
Self::NotARecord { reference }
}
fn schema(reference: ResourceRef, expected: &'static str, found: String) -> Self {
Self::Schema {
reference,
expected,
found,
}
}
fn damaged_schema(reference: ResourceRef) -> Self {
Self::DamagedSchema { reference }
}
fn missing_field(reference: ResourceRef, field: &'static str) -> Self {
Self::MissingField { reference, field }
}
fn unknown_field(reference: ResourceRef, schema: &'static str, field: String) -> Self {
Self::UnknownField {
reference,
schema,
field,
}
}
fn field_type(reference: ResourceRef, field: &'static str) -> Self {
Self::FieldType {
reference,
schema: PRICE_BOOK_SCHEMA,
field,
}
}
}
impl DisplayNameError for PricingError {
fn malformed_display_name(
reference: ResourceRef,
field: &'static str,
source: InvalidDisplayName,
) -> Self {
Self::MalformedCitation {
reference,
field,
source,
}
}
}
trait PriceFields<'a> {
fn catalog_id(&self, field: &'static str) -> Result<ProviderId, PricingError>;
fn actor(&self, field: &'static str) -> Result<Actor, PricingError>;
fn instant(&self, field: &'static str) -> Result<EffectiveInstant, PricingError>;
fn optional_instant(
&self,
field: &'static str,
) -> Result<Option<EffectiveInstant>, PricingError>;
fn rate(
&self,
target: &PricedTarget,
field: &'static str,
) -> Result<ApprovedRate, PricingError>;
fn optional_rate(
&self,
target: &PricedTarget,
field: &'static str,
) -> Result<Option<ApprovedRate>, PricingError>;
fn reject_tiers(&self, field: &'static str) -> Result<(), RateRejection>;
}
impl<'a> PriceFields<'a> for Record<'a, PricingError> {
fn catalog_id(&self, field: &'static str) -> Result<ProviderId, PricingError> {
ProviderId::parse(self.string(field)?).map_err(|source| PricingError::MalformedId {
reference: self.reference(),
field,
source,
})
}
fn actor(&self, field: &'static str) -> Result<Actor, PricingError> {
Actor::read(self.value(field)?).map_err(|source| PricingError::MalformedActor {
reference: self.reference(),
field,
source,
})
}
fn instant(&self, field: &'static str) -> Result<EffectiveInstant, PricingError> {
u64::try_from(self.signed_integer(field)?)
.map(EffectiveInstant::from_millis)
.map_err(|_| PricingError::MalformedInstant {
reference: self.reference(),
field,
})
}
fn optional_instant(
&self,
field: &'static str,
) -> Result<Option<EffectiveInstant>, PricingError> {
match self.optional_value(field) {
None => Ok(None),
Some(_) => self.instant(field).map(Some),
}
}
fn rate(
&self,
target: &PricedTarget,
field: &'static str,
) -> Result<ApprovedRate, PricingError> {
let value = self.signed_integer(field)?;
let rejection = |source| PricingError::Rate {
reference: self.reference(),
target: target.to_string(),
source,
};
if value < 0 {
return Err(rejection(RateRejection::Negative { field, value }));
}
u64::try_from(value)
.map(ApprovedRate::from_nanos)
.map_err(|_| rejection(RateRejection::Overflow { field, value }))
}
fn optional_rate(
&self,
target: &PricedTarget,
field: &'static str,
) -> Result<Option<ApprovedRate>, PricingError> {
match self.optional_value(field) {
None => Ok(None),
Some(_) => self.rate(target, field).map(Some),
}
}
fn reject_tiers(&self, field: &'static str) -> Result<(), RateRejection> {
let Some(value) = self.optional_value(field) else {
return Ok(());
};
let tiers = match value {
CanonicalValue::List(tiers) | CanonicalValue::Set(tiers) => tiers,
_ => {
return Err(RateRejection::UnsupportedTier {
threshold: "unrecognized".to_owned(),
});
}
};
Err(RateRejection::UnsupportedTier {
threshold: tiers
.first()
.map_or_else(|| "empty".to_owned(), tier_threshold_name),
})
}
}
fn tier_threshold_name(tier: &CanonicalValue) -> String {
let CanonicalValue::Map(fields) = tier else {
return "unrecognized".to_owned();
};
let Some((_, CanonicalValue::Map(threshold))) =
fields.iter().find(|(name, _)| name == THRESHOLD_FIELD)
else {
return "unrecognized".to_owned();
};
match threshold.iter().find(|(name, _)| name == TYPE_FIELD) {
Some((_, CanonicalValue::String(kind))) => kind.clone(),
_ => "unrecognized".to_owned(),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::desired_state::fixtures;
const MICRO: u64 = 1_000;
fn target() -> PricedTarget {
fixtures::priced_target("openai", "gpt-4o")
}
fn at(millis: u64) -> EffectiveInstant {
EffectiveInstant::from_millis(millis)
}
fn approved() -> Approval {
Approval::Approved {
by: fixtures::actor(),
at: EffectiveInstant::EPOCH,
citation: None,
}
}
fn book_of(body: &PriceBookBody) -> PriceBook {
let resource = fixtures::price_book(body, 7, "baseline");
let mut state = fixtures::state();
state.insert(resource).expect("a distinct reference");
PriceBooks::of(&state)
.expect("the book is readable")
.book()
.expect("the state holds a book")
.clone()
}
#[test]
fn an_approved_book_round_trips_through_its_canonical_body() {
let body = fixtures::approved_price_book();
let read = PriceBookBody::read(&fixtures::price_book(&body, 7, "baseline"))
.expect("the fixture body is readable");
assert_eq!(read, body);
assert_eq!(read.catalog(), fixtures::catalog_content_id());
assert_eq!(read.currency(), Currency::Usd);
assert_eq!(read.unit(), RateUnit::NanoDollarsPerMillionTokens);
assert!(read.approval().is_approved());
}
#[test]
fn a_books_checksum_does_not_depend_on_the_order_its_rules_were_added_in() {
let first = fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::bounded(EffectiveInstant::EPOCH, at(10)).expect("non-empty"),
MICRO,
MICRO,
);
let second = fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::from(at(10)),
2 * MICRO,
2 * MICRO,
);
let forwards = PriceBookBody::new(fixtures::catalog_content_id(), approved())
.with_rule(first.clone())
.with_rule(second.clone());
let backwards = PriceBookBody::new(fixtures::catalog_content_id(), approved())
.with_rule(second)
.with_rule(first);
assert_eq!(
forwards.canonical().checksum().expect("canonical"),
backwards.canonical().checksum().expect("canonical")
);
}
#[test]
fn a_rate_at_whole_micro_dollars_converts_exactly() {
let rates = ApprovedRates {
reasoning: Some(ApprovedRate::from_nanos(7 * MICRO)),
cache_read: Some(ApprovedRate::ZERO),
..ApprovedRates::new(
ApprovedRate::from_nanos(2_500_000),
ApprovedRate::from_nanos(10_000_000),
)
};
let price = rates.to_model_price().expect("whole micro-dollars convert");
assert_eq!(price.input_microdollars_per_million, 2_500);
assert_eq!(price.output_microdollars_per_million, 10_000);
assert_eq!(price.reasoning_microdollars_per_million, Some(7));
assert_eq!(price.cache_read_microdollars_per_million, Some(0));
assert_eq!(price.cache_write_microdollars_per_million, None);
}
#[test]
fn a_rate_finer_than_a_micro_dollar_is_refused_rather_than_rounded() {
let rates = ApprovedRates::new(
ApprovedRate::from_nanos(1_500),
ApprovedRate::from_nanos(MICRO),
);
assert_eq!(
rates.to_model_price(),
Err(RateRejection::ExcessPrecision {
field: "input",
nanos: 1_500
})
);
let boundary = ApprovedRates::new(ApprovedRate::from_nanos(999), ApprovedRate::ZERO);
assert!(matches!(
boundary.to_model_price(),
Err(RateRejection::ExcessPrecision { .. })
));
}
#[test]
fn an_audio_rate_is_refused_because_no_usage_field_would_bill_it() {
let rates = ApprovedRates {
input_audio: Some(ApprovedRate::from_nanos(MICRO)),
..ApprovedRates::new(
ApprovedRate::from_nanos(MICRO),
ApprovedRate::from_nanos(MICRO),
)
};
assert_eq!(
rates.to_model_price(),
Err(RateRejection::UnbillableUsage {
field: "input_audio"
})
);
}
#[test]
fn approving_an_observed_rate_preserves_it_exactly() {
let observed = ObservedRate::from_nanos(3_000);
assert_eq!(ApprovedRate::approving(observed).nanos(), observed.nanos());
}
#[test]
fn an_effective_interval_includes_its_start_and_excludes_its_end() {
let interval = EffectiveInterval::bounded(at(100), at(200)).expect("non-empty");
assert!(!interval.contains(at(99)));
assert!(interval.contains(at(100)));
assert!(interval.contains(at(199)));
assert!(!interval.contains(at(200)));
}
#[test]
fn an_interval_that_contains_no_instant_is_refused() {
assert_eq!(
EffectiveInterval::bounded(at(100), at(100)),
Err(InvalidInterval::Empty {
from: at(100),
until: at(100)
})
);
assert!(EffectiveInterval::bounded(at(100), at(99)).is_err());
}
#[test]
fn consecutive_rules_hand_over_at_the_boundary_instant() {
let body = PriceBookBody::new(fixtures::catalog_content_id(), approved())
.with_rule(fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::bounded(EffectiveInstant::EPOCH, at(1_000)).expect("non-empty"),
MICRO,
MICRO,
))
.with_rule(fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::from(at(1_000)),
2 * MICRO,
2 * MICRO,
));
let book = book_of(&body);
let provider = target().provider;
let before = PricingSnapshot::of(&book, at(999));
let on = PricingSnapshot::of(&book, at(1_000));
assert_eq!(
before
.price(&provider, "gpt-4o")
.expect("priced")
.input_microdollars_per_million,
1
);
assert_eq!(
on.price(&provider, "gpt-4o")
.expect("priced")
.input_microdollars_per_million,
2
);
assert_eq!(before.effective().starts(), EffectiveInstant::EPOCH);
assert_eq!(before.effective().ends(), Some(at(1_000)));
assert_eq!(on.effective(), EffectiveInterval::from(at(1_000)));
}
#[test]
fn two_rules_of_one_precedence_covering_one_instant_are_refused() {
let body = PriceBookBody::new(fixtures::catalog_content_id(), approved())
.with_rule(fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::bounded(EffectiveInstant::EPOCH, at(1_001)).expect("non-empty"),
MICRO,
MICRO,
))
.with_rule(fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::from(at(1_000)),
2 * MICRO,
2 * MICRO,
));
let error = PriceBookBody::read(&fixtures::price_book(&body, 7, "baseline"))
.expect_err("overlapping rules of one precedence are refused");
assert!(matches!(
error,
PricingError::OverlappingRules {
precedence: RulePrecedence::Baseline,
..
}
));
assert!(!error.is_incompatible());
}
#[test]
fn an_override_supersedes_the_baseline_for_the_interval_it_covers() {
let body = PriceBookBody::new(fixtures::catalog_content_id(), approved())
.with_rule(fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::from(EffectiveInstant::EPOCH),
10 * MICRO,
10 * MICRO,
))
.with_rule(fixtures::price_rule(
target(),
RulePrecedence::Override,
EffectiveInterval::bounded(at(500), at(1_500)).expect("non-empty"),
4 * MICRO,
4 * MICRO,
));
let book = book_of(&body);
let provider = target().provider;
let priced = |instant| {
PricingSnapshot::of(&book, instant)
.price(&provider, "gpt-4o")
.expect("the baseline covers every instant")
.input_microdollars_per_million
};
assert_eq!(priced(at(499)), 10);
assert_eq!(priced(at(500)), 4);
assert_eq!(priced(at(1_499)), 4);
assert_eq!(priced(at(1_500)), 10);
}
#[test]
fn a_draft_book_activates_no_prices() {
let body = PriceBookBody::new(fixtures::catalog_content_id(), Approval::Draft).with_rule(
fixtures::price_rule(
target(),
RulePrecedence::Baseline,
EffectiveInterval::from(EffectiveInstant::EPOCH),
MICRO,
MICRO,
),
);
let snapshot = PricingSnapshot::of(&book_of(&body), at(5_000));
assert!(!snapshot.is_approved());
assert!(snapshot.is_empty());
assert_eq!(snapshot.price(&target().provider, "gpt-4o"), None);
}
#[test]
fn a_target_the_book_does_not_price_has_no_price() {
let snapshot = PricingSnapshot::of(&book_of(&fixtures::approved_price_book()), at(1));
assert!(snapshot.price(&target().provider, "gpt-4o").is_some());
assert_eq!(snapshot.price(&target().provider, "o3"), None);
assert_eq!(
snapshot.price(
&crate::backends::catalog::ProviderId::parse("anthropic").expect("id"),
"gpt-4o"
),
None
);
}
#[test]
fn a_config_provider_id_is_not_a_catalogue_provider_id() {
let snapshot = PricingSnapshot::of(&book_of(&fixtures::approved_price_book()), at(1));
let routed = "openai-primary";
let routed = ProviderId::parse(routed).expect("a config id can spell a catalogue id");
assert_eq!(snapshot.price(&routed, "gpt-4o"), None);
assert!(snapshot.price(&target().provider, "gpt-4o").is_some());
}
#[test]
fn a_snapshot_records_the_book_and_catalogue_it_priced_from() {
let body = fixtures::approved_price_book();
let book = book_of(&body);
let snapshot = PricingSnapshot::of(&book, at(1));
assert_eq!(snapshot.book(), book.reference);
assert_eq!(
snapshot.book(),
fixtures::price_book(&body, 7, "baseline").reference
);
assert_eq!(
snapshot.checksum(),
body.canonical().checksum().expect("canonical")
);
assert_eq!(snapshot.catalog(), fixtures::catalog_content_id());
assert_eq!(snapshot.targets().len(), 1);
}
#[test]
fn the_published_checksum_is_the_stored_bodys_checksum() {
let resource = fixtures::price_book(&fixtures::approved_price_book(), 7, "baseline");
let ResourceBody::Inline(stored) = &resource.body else {
panic!("a price book is inline");
};
let stored = stored.checksum().expect("a record has a checksum");
let mut state = fixtures::state();
state.insert(resource).expect("a distinct reference");
let book = PriceBooks::of(&state)
.expect("the book is readable")
.book()
.expect("the state holds a book")
.clone();
assert_eq!(book.checksum, stored);
assert_eq!(
PricingSnapshot::of(&book, at(1)).checksum(),
stored,
"the snapshot publishes the stored book's identity"
);
}
#[test]
fn a_body_this_build_would_have_to_read_lossily_is_refused() {
let empty_tiers = read_rule_with(|fields| {
fields.push((TIERS_FIELD.to_owned(), CanonicalValue::List(Vec::new())));
})
.expect_err("an empty tier list is refused");
let PricingError::Rate {
source: RateRejection::UnsupportedTier { threshold },
..
} = &empty_tiers
else {
panic!("expected a tier rejection, got {empty_tiers}");
};
assert_eq!(threshold, "empty");
let nested_schema = read_rule_with(|fields| {
fields.push((
SCHEMA_FIELD.to_owned(),
CanonicalValue::string(PRICE_BOOK_SCHEMA),
));
})
.expect_err("a nested schema key is refused");
let PricingError::UnknownField { field, .. } = &nested_schema else {
panic!("expected an unknown-field refusal, got {nested_schema}");
};
assert_eq!(field, SCHEMA_FIELD);
assert!(nested_schema.is_incompatible());
}
#[test]
fn a_revision_without_a_price_book_carries_no_approved_pricing() {
let books = PriceBooks::of(&fixtures::state()).expect("state without a book is valid");
assert!(books.book().is_none());
assert!(books.snapshot_at(at(1)).is_none());
}
#[test]
fn a_tenant_scoped_price_book_is_refused() {
let body = fixtures::approved_price_book();
let tenant = fixtures::tenant_id(1);
let resource = ResourceVersion::new(
fixtures::price_book(&body, 7, "baseline").reference,
ResourceScope::Tenant(tenant),
fixtures::price_book(&body, 7, "baseline").slug,
body.body(),
);
let mut state = fixtures::state();
state.insert(resource).expect("a distinct reference");
let error = PriceBooks::of(&state).expect_err("a tenant-scoped book is not servable");
assert!(matches!(error, PricingError::ScopeNotSupported { .. }));
assert!(error.is_incompatible());
}
#[test]
fn a_tenant_rate_row_is_not_the_deployments_baseline() {
let mut state = fixtures::state();
state
.insert(fixtures::price(&fixtures::tenant_id(1), 7, "acme-rate"))
.expect("a distinct reference");
let books =
PriceBooks::of(&state).expect("a tenant's rate row is not this slice's to read");
assert!(books.book().is_none(), "and it prices nothing");
assert!(books.snapshot_at(at(1)).is_none());
}
#[test]
fn a_tenant_rate_row_whose_marker_is_damaged_is_refused_here() {
let row = fixtures::price(&fixtures::tenant_id(1), 7, "acme-rate");
for marker in [
CanonicalValue::integer(1),
CanonicalValue::List(vec![CanonicalValue::string(PRICE_BOOK_SCHEMA)]),
CanonicalValue::map([(SCHEMA_FIELD, CanonicalValue::string(PRICE_BOOK_SCHEMA))]),
] {
let mut state = fixtures::state();
state
.insert(ResourceVersion::new(
row.reference,
row.scope.clone(),
row.slug.clone(),
ResourceBody::Inline(CanonicalValue::map([(SCHEMA_FIELD, marker.clone())])),
))
.expect("a distinct reference");
let error = PriceBooks::of(&state).expect_err("a marker no release wrote is refused");
assert!(
matches!(error, PricingError::DamagedSchema { .. }),
"{marker:?}: {error}"
);
assert!(
!error.is_incompatible(),
"storage to repair, not a build to roll forward: {error}"
);
}
}
#[test]
fn two_deployment_price_books_are_refused() {
let body = fixtures::approved_price_book();
let mut state = fixtures::state();
state
.insert(fixtures::price_book(&body, 7, "baseline"))
.and_then(|state| state.insert(fixtures::price_book(&body, 8, "second")))
.expect("distinct references");
assert!(matches!(
PriceBooks::of(&state),
Err(PricingError::MultipleBooks { .. })
));
}
#[test]
fn a_second_book_is_a_duplicate_before_it_is_anything_else() {
let body = fixtures::approved_price_book();
let CanonicalValue::Map(mut fields) = body.canonical() else {
panic!("a body is a record");
};
fields.retain(|(name, _)| name != CURRENCY_FIELD);
fields.push((CURRENCY_FIELD.to_owned(), CanonicalValue::string("EUR")));
let first = fixtures::price_book(&body, 7, "baseline");
let second = ResourceVersion::new(
fixtures::reference(ResourceKind::Price, 8),
ResourceScope::Deployment,
first.slug.clone(),
ResourceBody::Inline(CanonicalValue::map(fields)),
);
assert!(
first.reference < second.reference,
"the readable book has to be the one visited first for this to test the ordering"
);
let mut state = fixtures::state();
state
.insert(first)
.and_then(|state| state.insert(second))
.expect("distinct references");
let error = PriceBooks::of(&state).expect_err("two books are refused");
assert!(
matches!(error, PricingError::MultipleBooks { .. }),
"{error}"
);
assert!(!error.is_incompatible());
}
#[test]
fn a_second_book_is_a_duplicate_before_its_scope_is_judged() {
let body = fixtures::approved_price_book();
let first = fixtures::price_book(&body, 7, "baseline");
let second = ResourceVersion::new(
fixtures::reference(ResourceKind::Price, 8),
ResourceScope::Tenant(fixtures::tenant_id(1)),
first.slug.clone(),
body.body(),
);
assert!(
first.reference < second.reference,
"the deployment book has to be the one visited first for this to test the ordering"
);
let mut state = fixtures::state();
state
.insert(first)
.and_then(|state| state.insert(second))
.expect("distinct references");
let error = PriceBooks::of(&state).expect_err("two books are refused");
assert!(
matches!(error, PricingError::MultipleBooks { .. }),
"{error}"
);
assert!(!error.is_incompatible());
}
#[test]
fn bodies_a_newer_release_could_have_written_are_incompatibilities() {
let cases: &[(&str, CanonicalValue)] = &[
(SCHEMA_FIELD, CanonicalValue::string("axond.price-book.v2")),
(CURRENCY_FIELD, CanonicalValue::string("EUR")),
(UNIT_FIELD, CanonicalValue::string("pico-dollars")),
];
for (field, value) in cases {
let error = read_with_field(field, value.clone())
.err()
.unwrap_or_else(|| panic!("`{field}` = {value:?} is refused"));
assert!(error.is_incompatible(), "{field}: {error}");
}
let unknown = read_with_field("rebate", CanonicalValue::integer(1))
.expect_err("an unknown field is refused");
assert!(matches!(unknown, PricingError::UnknownField { .. }));
assert!(unknown.is_incompatible());
let untyped = read_without_field(SCHEMA_FIELD).expect_err("an untyped body is refused");
assert!(matches!(
untyped,
PricingError::MissingField {
field: SCHEMA_FIELD,
..
}
));
assert!(untyped.is_incompatible());
}
#[test]
fn bodies_no_release_would_have_written_are_invalid_state() {
for marker in [
CanonicalValue::integer(1),
CanonicalValue::List(vec![CanonicalValue::string(PRICE_BOOK_SCHEMA)]),
CanonicalValue::map([(SCHEMA_FIELD, CanonicalValue::string(PRICE_BOOK_SCHEMA))]),
] {
let damaged = read_with_field(SCHEMA_FIELD, marker.clone())
.expect_err("a schema marker that is not an identifier is refused");
assert!(
matches!(damaged, PricingError::DamagedSchema { .. }),
"{marker:?}: {damaged}"
);
assert!(!damaged.is_incompatible(), "{damaged}");
}
let missing = read_without_field(CURRENCY_FIELD).expect_err("a missing field is refused");
assert!(matches!(missing, PricingError::MissingField { .. }));
assert!(!missing.is_incompatible());
let mistyped = read_with_field(CURRENCY_FIELD, CanonicalValue::integer(840))
.expect_err("a mistyped field is refused");
assert!(matches!(mistyped, PricingError::FieldType { .. }));
assert!(!mistyped.is_incompatible());
let not_a_record = PriceBookBody::read(&ResourceVersion::new(
fixtures::reference(ResourceKind::Price, 7),
ResourceScope::Deployment,
fixtures::price_book(&fixtures::approved_price_book(), 7, "baseline").slug,
ResourceBody::Inline(CanonicalValue::integer(1)),
))
.expect_err("a non-record body is refused");
assert!(matches!(not_a_record, PricingError::NotARecord { .. }));
assert!(!not_a_record.is_incompatible());
}
#[test]
fn a_body_no_writer_could_have_encoded_names_its_encoding() {
let CanonicalValue::Map(mut fields) = fixtures::approved_price_book().canonical() else {
panic!("a body is a record");
};
let Some((_, CanonicalValue::Set(rules))) =
fields.iter().find(|(name, _)| name == RULES_FIELD)
else {
panic!("a body carries a rule set");
};
let CanonicalValue::Map(mut rule) = rules.first().expect("one rule").clone() else {
panic!("a rule is a record");
};
rule.retain(|(name, _)| name != MODEL_FIELD);
rule.push((
MODEL_FIELD.to_owned(),
CanonicalValue::string("gpt-4o\u{1}"),
));
fields.retain(|(name, _)| name != RULES_FIELD);
fields.push((
RULES_FIELD.to_owned(),
CanonicalValue::set([CanonicalValue::map(rule)]),
));
let mut state = fixtures::state();
state
.insert(ResourceVersion::new(
fixtures::reference(ResourceKind::Price, 7),
ResourceScope::Deployment,
fixtures::price_book(&fixtures::approved_price_book(), 7, "baseline").slug,
ResourceBody::Inline(CanonicalValue::map(fields)),
))
.expect("a distinct reference");
let error = PriceBooks::of(&state).expect_err("a body with no checksum has no identity");
assert!(
matches!(
error,
PricingError::Uncanonicalizable {
source: CanonicalError::ControlCharacter { .. },
..
}
),
"{error}"
);
assert!(!error.is_incompatible());
}
#[test]
fn rules_stated_in_an_order_are_refused_rather_than_fingerprinted() {
let CanonicalValue::Map(fields) = fixtures::approved_price_book().canonical() else {
panic!("a body is a record");
};
let Some((_, CanonicalValue::Set(rules))) =
fields.iter().find(|(name, _)| name == RULES_FIELD)
else {
panic!("a body carries a rule set");
};
let error = read_with_field(RULES_FIELD, CanonicalValue::List(rules.clone()))
.expect_err("an ordered rule field is refused");
assert!(
matches!(
error,
PricingError::FieldType {
field: RULES_FIELD,
..
}
),
"{error}"
);
}
#[test]
fn a_rate_this_build_cannot_bill_is_read_as_an_incompatibility() {
let error = read_rule_with(|fields| {
fields.push((
RATES_FIELD.to_owned(),
CanonicalValue::map([
(INPUT_FIELD, CanonicalValue::integer(1_500)),
(OUTPUT_FIELD, CanonicalValue::integer(1_000)),
]),
));
})
.expect_err("a rate finer than a micro-dollar is refused");
assert!(matches!(
error,
PricingError::Rate {
source: RateRejection::ExcessPrecision { .. },
..
}
));
assert!(error.is_incompatible());
}
#[test]
fn a_negative_rate_is_refused() {
let error = read_rule_with(|fields| {
fields.push((
RATES_FIELD.to_owned(),
CanonicalValue::map([
(INPUT_FIELD, CanonicalValue::integer(-1_000)),
(OUTPUT_FIELD, CanonicalValue::integer(1_000)),
]),
));
})
.expect_err("a negative rate is refused");
assert!(matches!(
error,
PricingError::Rate {
source: RateRejection::Negative { .. },
..
}
));
assert!(error.to_string().contains(&target().to_string()));
assert!(error.to_string().contains(INPUT_FIELD));
assert!(!error.is_incompatible());
}
#[test]
fn a_rate_beyond_the_units_range_is_refused_as_an_overflow() {
let error = read_rule_with(|fields| {
fields.push((
RATES_FIELD.to_owned(),
CanonicalValue::map([
(
INPUT_FIELD,
CanonicalValue::Integer(i128::from(u64::MAX) + 1),
),
(OUTPUT_FIELD, CanonicalValue::integer(1_000)),
]),
));
})
.expect_err("a rate past the range is refused");
assert!(matches!(
error,
PricingError::Rate {
source: RateRejection::Overflow { .. },
..
}
));
assert!(error.to_string().contains(&target().to_string()));
assert!(!error.is_incompatible());
}
#[test]
fn a_context_tiered_schedule_is_refused_naming_the_threshold() {
let error = read_rule_with(|fields| {
fields.push((
TIERS_FIELD.to_owned(),
CanonicalValue::List(vec![CanonicalValue::map([(
THRESHOLD_FIELD,
CanonicalValue::map([
(TYPE_FIELD, CanonicalValue::string("context_over")),
("tokens", CanonicalValue::integer(128_000)),
]),
)])]),
));
})
.expect_err("a tiered schedule is refused");
let PricingError::Rate {
source: RateRejection::UnsupportedTier { threshold },
..
} = &error
else {
panic!("expected a tier rejection, got {error}");
};
assert_eq!(threshold, "context_over");
assert!(error.is_incompatible());
}
#[test]
fn unknown_enumerated_spellings_are_incompatibilities() {
let precedence = read_rule_with(|fields| {
fields.retain(|(name, _)| name != PRECEDENCE_FIELD);
fields.push((
PRECEDENCE_FIELD.to_owned(),
CanonicalValue::string("contractual"),
));
})
.expect_err("an unknown precedence is refused");
assert!(matches!(precedence, PricingError::UnknownPrecedence { .. }));
assert!(precedence.is_incompatible());
let state = read_with_field(
APPROVAL_FIELD,
CanonicalValue::map([(STATE_FIELD, CanonicalValue::string("countersigned"))]),
)
.expect_err("an unknown approval state is refused");
assert!(matches!(state, PricingError::UnknownApprovalState { .. }));
assert!(state.is_incompatible());
}
#[test]
fn a_citation_this_build_will_not_take_is_read_as_an_incompatibility() {
let error = read_with_field(
APPROVAL_FIELD,
CanonicalValue::map([
(STATE_FIELD, CanonicalValue::string("approved")),
(APPROVED_BY_FIELD, fixtures::actor().canonical()),
(APPROVED_AT_FIELD, CanonicalValue::integer(1)),
(CITATION_FIELD, CanonicalValue::string(" CHG-1")),
]),
)
.expect_err("an unreadable citation is refused");
assert!(matches!(
error,
PricingError::MalformedCitation {
field: CITATION_FIELD,
..
}
));
assert!(
error.is_incompatible(),
"a citation rule that tightened is skew, not damage: {error}"
);
}
#[test]
fn an_unreadable_identity_is_read_as_damage_and_not_as_skew() {
let checksum = read_with_field(CATALOG_FIELD, CanonicalValue::string("sha512:beef"))
.expect_err("a digest this build does not state is refused");
assert!(matches!(
checksum,
PricingError::MalformedChecksum {
field: CATALOG_FIELD,
..
}
));
assert!(
!checksum.is_incompatible(),
"an identity nothing can verify is damage: {checksum}"
);
let provider = read_rule_with(|fields| {
fields.retain(|(name, _)| name != PROVIDER_FIELD);
fields.push((PROVIDER_FIELD.to_owned(), CanonicalValue::string("Open AI")));
})
.expect_err("an unreadable provider id is refused");
assert!(matches!(
provider,
PricingError::MalformedId {
field: PROVIDER_FIELD,
..
}
));
assert!(
!provider.is_incompatible(),
"a target nothing can route to is damage: {provider}"
);
}
#[test]
fn a_draft_book_carrying_approval_evidence_is_refused() {
for field in [APPROVED_BY_FIELD, APPROVED_AT_FIELD, CITATION_FIELD] {
let value = match field {
APPROVED_BY_FIELD => fixtures::actor().canonical(),
APPROVED_AT_FIELD => CanonicalValue::integer(1),
_ => CanonicalValue::string("CHG-1"),
};
let error = read_with_field(
APPROVAL_FIELD,
CanonicalValue::map([
(STATE_FIELD, CanonicalValue::string("draft")),
(field, value),
]),
)
.expect_err("a draft naming an approval is refused");
let PricingError::UnknownField { field: named, .. } = &error else {
panic!("expected an unknown-field refusal, got {error}");
};
assert_eq!(named, field);
assert!(error.is_incompatible(), "dropped evidence is skew: {error}");
}
}
#[test]
fn an_approved_book_with_no_readable_approver_is_refused() {
let error = read_with_field(
APPROVAL_FIELD,
CanonicalValue::map([
(STATE_FIELD, CanonicalValue::string("approved")),
(APPROVED_AT_FIELD, CanonicalValue::integer(1)),
]),
)
.expect_err("an approval without an approver is refused");
assert!(matches!(
error,
PricingError::MissingField { field: "by", .. }
));
}
#[test]
fn an_approver_a_newer_release_wrote_is_read_as_an_incompatibility() {
for approver in [
CanonicalValue::map([
("kind", CanonicalValue::string("human")),
("issuer", CanonicalValue::string("https://idp.example")),
("subject", CanonicalValue::string("ops@example")),
("assurance", CanonicalValue::string("webauthn")),
]),
CanonicalValue::map([("kind", CanonicalValue::string("delegate"))]),
] {
let error = read_with_field(
APPROVAL_FIELD,
CanonicalValue::map([
(STATE_FIELD, CanonicalValue::string("approved")),
(APPROVED_BY_FIELD, approver),
(APPROVED_AT_FIELD, CanonicalValue::integer(1)),
]),
)
.expect_err("an approver this build cannot read is refused");
assert!(matches!(error, PricingError::MalformedActor { .. }));
assert!(
error.is_incompatible(),
"an approver a newer release wrote is skew, not damage: {error}"
);
}
}
#[test]
fn a_resolution_at_the_end_of_the_timeline_has_no_boundary_after_it() {
let last = EffectiveInstant::from_millis(u64::MAX);
let body = PriceBookBody::new(fixtures::catalog_content_id(), approved()).with_rule(
PriceRule::new(
fixtures::priced_target("openai", "gpt-5.5"),
RulePrecedence::Baseline,
EffectiveInterval::bounded(EffectiveInstant::EPOCH, last).expect("non-empty"),
ApprovedRates::new(
ApprovedRate::from_nanos(1_000),
ApprovedRate::from_nanos(2_000),
),
PriceProvenance::stated(PriceOrigin::Catalogue),
)
.expect("billable"),
);
let snapshot = PricingSnapshot::of(&book_of(&body), last);
assert_eq!(snapshot.effective().starts(), last);
assert_eq!(snapshot.effective().ends(), None);
assert_eq!(snapshot.targets().len(), 0);
}
#[test]
fn a_service_account_can_approve_a_book() {
let by = Actor::Workload {
tenant: fixtures::tenant_id(1),
principal: fixtures::principal_id(9),
};
let body = PriceBookBody::new(
fixtures::catalog_content_id(),
Approval::Approved {
by: by.clone(),
at: EffectiveInstant::EPOCH,
citation: None,
},
);
let read =
PriceBookBody::read(&fixtures::price_book(&body, 7, "baseline")).expect("readable");
assert_eq!(read.approval().approver(), Some(&by));
assert_eq!(read, body, "and the book itself round trips");
}
#[test]
fn a_workload_approver_without_its_principal_is_damaged() {
let error = read_with_field(
APPROVAL_FIELD,
CanonicalValue::map([
(STATE_FIELD, CanonicalValue::string("approved")),
(
APPROVED_BY_FIELD,
CanonicalValue::map([
("kind", CanonicalValue::string("workload")),
(
"tenant",
CanonicalValue::string(fixtures::tenant_id(1).to_string()),
),
]),
),
(APPROVED_AT_FIELD, CanonicalValue::integer(1)),
]),
)
.expect_err("an approver missing its principal is refused");
assert!(matches!(error, PricingError::MalformedActor { .. }));
assert!(
!error.is_incompatible(),
"a known approver kind missing a field is damage: {error}"
);
}
#[test]
fn an_approval_records_its_approver_and_citation() {
let body = fixtures::approved_price_book();
let read =
PriceBookBody::read(&fixtures::price_book(&body, 7, "baseline")).expect("readable");
let Approval::Approved { by, at, citation } = read.approval() else {
panic!("the fixture book is approved");
};
assert_eq!(by, &fixtures::actor());
assert_eq!(*at, EffectiveInstant::EPOCH);
assert_eq!(citation.as_ref().map(DisplayName::as_str), Some("CHG-1"));
}
#[test]
fn a_revision_carrying_an_unbillable_book_does_not_validate() {
let body = PriceBookBody::new(fixtures::catalog_content_id(), approved());
let resource = fixtures::price_book(&body, 7, "baseline");
let mut state = fixtures::state();
state.insert(resource).expect("a distinct reference");
state.validate().expect("an empty book is valid");
let mut broken = fixtures::state();
broken
.insert(ResourceVersion::new(
fixtures::reference(ResourceKind::Price, 7),
ResourceScope::Deployment,
fixtures::price_book(&body, 7, "baseline").slug,
ResourceBody::Inline(CanonicalValue::map([(
SCHEMA_FIELD,
CanonicalValue::string("axond.price-book.v99"),
)])),
))
.expect("a distinct reference");
let error = broken
.validate()
.expect_err("an unreadable book is not publishable");
assert!(error.to_string().contains("price-book"), "{error}");
}
#[test]
fn an_instant_off_the_timeline_is_refused_rather_than_clamped() {
assert_eq!(
EffectiveInstant::of(SystemTime::UNIX_EPOCH).expect("the epoch is on the timeline"),
EffectiveInstant::EPOCH
);
assert_eq!(
EffectiveInstant::of(SystemTime::UNIX_EPOCH - Duration::from_millis(1)),
Err(InvalidInstant::BeforeEpoch)
);
let instant = at(1_700_000_000_000);
assert_eq!(
EffectiveInstant::of(instant.to_system_time().expect("a representable instant"))
.expect("round trip"),
instant
);
let far = EffectiveInstant::from_millis(u64::MAX);
if let Some(time) = far.to_system_time() {
assert_eq!(EffectiveInstant::of(time), Ok(far));
}
}
fn read_with_field(field: &str, value: CanonicalValue) -> Result<PriceBookBody, PricingError> {
let CanonicalValue::Map(mut fields) = fixtures::approved_price_book().canonical() else {
panic!("a body is a record");
};
fields.retain(|(name, _)| name != field);
fields.push((field.to_owned(), value));
read_body(CanonicalValue::map(fields))
}
fn read_without_field(field: &str) -> Result<PriceBookBody, PricingError> {
let CanonicalValue::Map(mut fields) = fixtures::approved_price_book().canonical() else {
panic!("a body is a record");
};
fields.retain(|(name, _)| name != field);
read_body(CanonicalValue::map(fields))
}
fn read_rule_with(
mutate: impl FnOnce(&mut Vec<(String, CanonicalValue)>),
) -> Result<PriceBookBody, PricingError> {
let CanonicalValue::Map(fields) = fixtures::approved_price_book().canonical() else {
panic!("a body is a record");
};
let Some((_, CanonicalValue::Set(rules))) =
fields.iter().find(|(name, _)| name == RULES_FIELD)
else {
panic!("a body carries a rule set");
};
let CanonicalValue::Map(mut rule) = rules.first().expect("one rule").clone() else {
panic!("a rule is a record");
};
mutate(&mut rule);
let mut seen = std::collections::BTreeSet::new();
rule.reverse();
rule.retain(|(name, _)| seen.insert(name.clone()));
let mut fields = fields;
fields.retain(|(name, _)| name != RULES_FIELD);
fields.push((
RULES_FIELD.to_owned(),
CanonicalValue::set([CanonicalValue::map(rule)]),
));
read_body(CanonicalValue::map(fields))
}
fn read_body(value: CanonicalValue) -> Result<PriceBookBody, PricingError> {
PriceBookBody::read(&ResourceVersion::new(
fixtures::reference(ResourceKind::Price, 7),
ResourceScope::Deployment,
fixtures::price_book(&fixtures::approved_price_book(), 7, "baseline").slug,
ResourceBody::Inline(value),
))
}
}