The cost pricing registry
The engine reads this file and a human writes it: rates, named zeros, and what the ledger does with them.
What it is. The engine normalizes every run's cost onto one USD column, but it never
invents a rate. For a token-unit backend (codex, agent-loop, qwen-code), the rate — or the fact
that there is no marginal rate at all — is a human declaration, read from one JSON file
in the workspace. The engine reads this file. A human writes it. No verb creates it,
edits it, or guesses a rate for it.
Where it lives. <workspace>/bridge/registry/pricing.json, workspace-relative. A
missing file is not an error — it is the empty table, and every run priced against it
books the honest string "unknown" rather than a silent $0.
Shape.
Match is by (backend, model) — the first row that matches wins; there is no fallback to a
"default" rate for a backend with no matching row.
The two kinds a row can declare, for a token-unit backend:
- A rate row.
input_usd_per_1m/output_usd_per_1m— the row prices the run's own token counters at that rate. Use this when the backend genuinely bills per token. - A named zero.
kind: "subscription-covered"(forcodexon a human-paid subscription account) orkind: "local-energy"(foragent-loopon a self-hosted endpoint, and forqwen-codepointed at a model you run yourself) — the marginal USD for the run is genuinely zero, but that zero is declared and named, never guessed from the seat's auth mode. A named-zero row wins before any rate math. The kinds are backend-specific: acodexrow usinglocal-energy(or the reverse) does not win the named-zero branch and stays"unknown".
⚠ qwen-code needs a row PER MODEL, and its two model families genuinely differ. One
qwen seat legitimately spans both: a local .gguf path the owner serves himself is
local-energy, while a served tag reached through an API key is metered and carries real
rates. Do not try to express that split on the seat — the seat's billing class is one value
for the whole seat, and (backend, model) is what the pricing table is already keyed by:
And for qwen-code a rate row does not yet produce a number. This engine captures no
token counters from that backend's output — what it reports is tokens rather than money, and
the shape of its streaming output has never been measured here — so a rated run on that backend
normalizes to "unknown" naming that gap, deliberately, rather than multiplying real rates
by zero unread tokens and booking a confident $0.00. The local-energy row is unaffected
and works today: its zero is your declaration, not arithmetic over counters.
One structural exception exists so an unregistered local model cannot masquerade as vendor
spend: an openai-compat run against a loopback base URL with no matching row is priced
local-energy from the observed loopback fact itself. A non-loopback URL with no row stays
honestly unknown.
What changes in the ledger once a row is declared.
- No row for the model:
saphan runandsaphan dispatch commandprint a pre-flight warning naming the model and this file, but the run still spawns — the engine transports, it never refuses over a missing owner declaration. The run books"unknown";saphan cost <stream>andsaphan ledger showreport it in theirunknown_cost_runscount and name the model — the blind spot leaves a trace in the rollup instead of silently vanishing from the total. - A named-zero (or rate) row matches: the warning does not fire, the run books a real,
countable figure (
"0"for the declared-zero case, with the reason named in itspricing_ref), and the run drops out of the unknown-cost counts.
Declaring a row is the owner's own act, off-engine — write the file by hand, through whatever change-review process your workspace already uses. The full economics — billing classes on seats, cost classes in the ledger, and what the dashboard draws from them — are Cost management.
Remote repositories and admission mirrors
Guarding admission commits, keeping a machine's mirror fresh, and a machine that serves more than one repository.
Starting the authorization server for the first time
Deciding how the connection is encrypted, writing the settings, minting the first signing key.