Skip to main content

Module charge

Module charge 

Source
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:

ShapeWhy it lands right
An MRTR chain of any lengthOnly its final round trip is resultType: "complete", so it bills once
An abandoned chainNever reaches complete, so it bills nothing
A task polled 300 timesOnly the poll reporting status: "completed" delivered anything
A task that fails or is cancelledTerminal, but delivered nothing, so nothing is owed
Discovery trafficNever billable; it is the cost of connecting
A protocol errorThe 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.
TaskAttribution
Pre-priced durable-task attribution without the original name or URI.

Enums§

Charge
The verdict.
FreeReason
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.
TaskOriginKind
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.