Expand description
The billing decision: what a request/response pair is worth.
§The rule
Charge on terminal delivery, never on request.
Every consequence a meter needs falls out of that one sentence, with no chain correlation, no session, and no state:
| Shape | Why it lands right |
|---|---|
| An MRTR chain of any length | Only its final round trip is resultType: "complete", so it bills once |
| An abandoned chain | Never reaches complete, so it bills nothing |
| A task polled 300 times | Only the poll reporting status: "completed" delivered anything |
| A task that fails or is cancelled | Terminal, but delivered nothing, so nothing is owed |
| Discovery traffic | Never billable; it is the cost of connecting |
| A protocol error | The server failed; charging for that is indefensible |
This replaced an earlier design that tried to collapse MRTR chains by
correlating their round trips. That design cannot be built by an intermediary:
requestState is “an opaque string meaningful only to the server”, which
servers MUST integrity-protect with HMAC or AEAD, so the only correlator on
the wire is encrypted under a key the meter does not hold. Charging on
delivery needs no correlator, which is why it is both correct and cheaper.
§Continuation state
It does not consider whether the request was a continuation. Under the rule
above that fact is irrelevant to billing, and requiring it would force a body
peek on every tools/call. crate::peek::request still exposes it for the
cache, because MRTR-derived results MUST NOT be cached.
§Replay
Two double-billing vectors exist, and they are treated differently on purpose.
A terminal task can be polled forever. Terminal state “does not change”, so
every later tasks/get reports completed again. That is one unit of work
reported many times, so Billable::idempotency_key carries the taskId and
the caller MUST suppress repeats.
A replayed MRTR continuation may produce a second complete. The spec
bounds the replay window but explicitly does not guarantee single use. We bill
it because the origin executed the tool a second time. Two completed executions
produce two charges.
Structs§
- Billable
- A charge to record against a tenant.
- Call
- The call being priced, as known from its (trusted) headers.
- Task
Attribution - Pre-priced durable-task attribution without the original name or URI.
Enums§
- Charge
- The verdict.
- Free
Reason - Why a call was not billed. Kept specific so an operator answering “why is my bill lower than my request count” gets a real answer from the metrics.
- Task
Origin Kind - Non-identifying method category retained for a durable task.
Functions§
- decide
- Decide what a completed request/response exchange is worth.
- decide_
with_ task_ attribution - Decide an exchange using pre-priced, non-identifying task attribution.
- decide_
with_ task_ origin - Decide an exchange while supplying the call that created a polled task.