connector-spend (B3c): reserve-then-settle spend in the replay ledger, one charge owner, a windowed per-caller ceiling (squash of eureka-body/connector-spend 1d51e71..45d0927)
The reservation and the replay claim are one write in the connector's replay store; a failed ledger write runs nothing. Amounts are integer micro-USD with checked arithmetic, and the service derives every cost from usage and the configured price. One function, ProviderCall::charge, decides the charge: a result bound to its request and caller pays its true cost with a truthful overrun, anything else pays the reservation (ruling spend-bills-on-identity-not-validity). Each caller has a spend ceiling over fixed epoch-aligned windows in its root-owned config (connector-spend-caller-window-ceiling); the admission window is monotonic, so a clock stepping back cannot reopen budget, and a clock-locked caller is refused ClockBehindAdmissionWindow (spend-window-clock-ahead-fails-closed). Refusals CostBound, SpendCeiling and ClockBehindAdmissionWindow are typed. Spec eureka-body:cut_spec:cut-connector-spend.r1; reports h1-h5; Soul s5 holds (verdict eureka-body:verdict:cut-connector-spend.s5). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
1d51e71ebf
commit
e0c0832ae0
17 changed files with 2342 additions and 76 deletions
|
|
@ -11,6 +11,12 @@
|
|||
"format": "uint64",
|
||||
"minimum": 0
|
||||
},
|
||||
"max_cost_micro_usd": {
|
||||
"description": "The most this request may cost, in micro-USD: the caller's own bound\non it. Required nonzero. It is part of the invocation's identity, so a\nchanged budget under a recorded request id is a `ReplayConflict`.",
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0
|
||||
},
|
||||
"native_request_sha256": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
|
|
@ -47,6 +53,7 @@
|
|||
"expires_at_unix_ms",
|
||||
"native_request_sha256",
|
||||
"provider_request_sha256",
|
||||
"max_cost_micro_usd",
|
||||
"request"
|
||||
],
|
||||
"$defs": {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,12 @@
|
|||
"caller_runtime_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"cost_micro_usd": {
|
||||
"description": "What the request cost, in micro-USD. The service derives it from the\noutcome's usage and its price table; a backend never writes it.",
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0
|
||||
},
|
||||
"foreign_reasoning_dropped": {
|
||||
"description": "How many foreign `ReasoningState` items the service removed from the\nrequest before the backend saw it.",
|
||||
"type": "integer",
|
||||
|
|
@ -29,6 +35,12 @@
|
|||
"outcome": {
|
||||
"$ref": "#/$defs/TransportOutcome"
|
||||
},
|
||||
"overrun_micro_usd": {
|
||||
"description": "How far `cost_micro_usd` exceeds what the service reserved for the\nrequest: zero unless the backend reported usage above the worst case\nthe request allowed, which is a breach of the backend's contract. The\ncost is still the true one and the caller's window is charged all of\nit. The service derives this; a backend never writes it.",
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -60,6 +72,8 @@
|
|||
"model",
|
||||
"provider",
|
||||
"foreign_reasoning_dropped",
|
||||
"cost_micro_usd",
|
||||
"overrun_micro_usd",
|
||||
"outcome"
|
||||
],
|
||||
"$defs": {
|
||||
|
|
@ -132,6 +146,17 @@
|
|||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"usage": {
|
||||
"description": "What the provider billed for the failed request: `Some` when it\nreported usage (`Some` of zeros when it billed nothing), `None`\nwhen unknown.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/$defs/Usage"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
@ -149,7 +174,7 @@
|
|||
]
|
||||
},
|
||||
"Usage": {
|
||||
"description": "Token accounting for one completed request. Cache reads and writes are\ncounted apart from plain input; `reasoning_tokens` is absent when the\nprovider does not report it.",
|
||||
"description": "Token accounting for one request, as the backend reports it; the service\nprices it. Cache reads and writes are counted apart from plain input.\n`output_tokens` includes reasoning tokens: `reasoning_tokens` is a detail\n(absent when the provider does not report it) and is never priced apart.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cache_read_tokens": {
|
||||
|
|
|
|||
|
|
@ -46,12 +46,15 @@
|
|||
"ModelNotAllowed",
|
||||
"OutputBound",
|
||||
"PayloadBound",
|
||||
"CostBound",
|
||||
"SpendCeiling",
|
||||
"Capacity",
|
||||
"InFlight",
|
||||
"Indeterminate",
|
||||
"ReplayConflict",
|
||||
"Malformed",
|
||||
"ForeignReasoningState"
|
||||
"ForeignReasoningState",
|
||||
"ClockBehindAdmissionWindow"
|
||||
]
|
||||
},
|
||||
"StopReason": {
|
||||
|
|
@ -250,6 +253,17 @@
|
|||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
},
|
||||
"usage": {
|
||||
"description": "What the provider billed for the failed request: `Some` when it\nreported usage (`Some` of zeros when it billed nothing), `None`\nwhen unknown.",
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/$defs/Usage"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"additionalProperties": false,
|
||||
|
|
@ -272,6 +286,12 @@
|
|||
"caller_runtime_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"cost_micro_usd": {
|
||||
"description": "What the request cost, in micro-USD. The service derives it from the\noutcome's usage and its price table; a backend never writes it.",
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0
|
||||
},
|
||||
"foreign_reasoning_dropped": {
|
||||
"description": "How many foreign `ReasoningState` items the service removed from the\nrequest before the backend saw it.",
|
||||
"type": "integer",
|
||||
|
|
@ -295,6 +315,12 @@
|
|||
"outcome": {
|
||||
"$ref": "#/$defs/TransportOutcome"
|
||||
},
|
||||
"overrun_micro_usd": {
|
||||
"description": "How far `cost_micro_usd` exceeds what the service reserved for the\nrequest: zero unless the backend reported usage above the worst case\nthe request allowed, which is a breach of the backend's contract. The\ncost is still the true one and the caller's window is charged all of\nit. The service derives this; a backend never writes it.",
|
||||
"type": "integer",
|
||||
"format": "uint64",
|
||||
"minimum": 0
|
||||
},
|
||||
"provider": {
|
||||
"type": "string"
|
||||
},
|
||||
|
|
@ -326,11 +352,13 @@
|
|||
"model",
|
||||
"provider",
|
||||
"foreign_reasoning_dropped",
|
||||
"cost_micro_usd",
|
||||
"overrun_micro_usd",
|
||||
"outcome"
|
||||
]
|
||||
},
|
||||
"Usage": {
|
||||
"description": "Token accounting for one completed request. Cache reads and writes are\ncounted apart from plain input; `reasoning_tokens` is absent when the\nprovider does not report it.",
|
||||
"description": "Token accounting for one request, as the backend reports it; the service\nprices it. Cache reads and writes are counted apart from plain input.\n`output_tokens` includes reasoning tokens: `reasoning_tokens` is a detail\n(absent when the provider does not report it) and is never priced apart.",
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"cache_read_tokens": {
|
||||
|
|
|
|||
Loading…
Reference in a new issue