Skip to content

pricing: an authoritative figure is labelled from the row that would have priced it, not from its endpoint #1183

Description

@huang195

Split out of #1153. The reachable half is fixed there; this is the narrower half, which needs an API change.

The rule the unit follows today

Table.CurrencyFor(endpoint, model) answers from bestRow(endpoint, model) — the same row Resolve prices from. That is deliberate and right for a table-priced figure: taking the unit from anywhere else would let a figure be priced at one row's rate and labelled with another's.

Where it is wrong

An authoritative figure — one the gateway reported, which settle publishes without consulting the table — is denominated in the gateway's unit. The row that would have priced it is irrelevant, and may not even be the endpoint's own row.

Measured, with a credits gateway beside a hosts: ["*"], models: {"*"} catch-all:

Resolve(gw.bob, "")     priced=true  prov=configured  rate=1e-06   <- the catch-all, in USD
CurrencyFor(gw.bob, "") "USD"                                      <- so USD is CORRECT here

For a table-priced figure that is the right answer. But if the gateway also reports its own cost, the authoritative figure wins in settle — and it is in credits while the label stays USD. The row gets no currency field and the read side folds it into the dollar total.

Why #1153 did not fix this half

CurrencyFor cannot see provenance. #1153 fixed the case where no row matches (host, model), which is provably safe to fix: no row means prov=none, so the table did not price it, so the figure must be authoritative and the endpoint's unit is the only correct answer. Verified:

Resolve(gw.bob, "")     priced=false prov=none
CurrencyFor(gw.bob, "") "credits"                                  <- after #1153

The remaining case needs the caller to say which figure it holds.

Shape of a fix

ledger.Writer.Record already knows the provenance (ev.Provenance, pricing.ProvAuthoritative). So either:

  • give Resolver a provenance-aware unit lookup, and have the writer use the endpoint-only answer for an authoritative figure; or
  • resolve the unit by host specificity alone whenever the figure is authoritative.

Resolver is an exported interface and core is consumed outside this repo, so widening it is a cross-repo change — which is why #1153 left it rather than guessing. Table.bestRowForHost (added by #1153) is the host-only lookup such a fix would call.

Reachable set

A non-USD endpoint, a gateway that reports its own cost, and a models pattern that matches the request — including a "*" catch-all. Bob is the motivating gateway and reports cost in usage.cost, so this is worth confirming against a live capture rather than assuming it is exotic.

Assisted-By: Claude (Anthropic AI) noreply@anthropic.com

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions