Charge authority (v1 frozen)
Verifiable authorization-to-charge continuity, without becoming an AI gateway.
Freeze: charge-authority-v1-freeze.md · Reviewer map: charge-authority-v1-reviewer-map.md
Product truth
QuantZK binds a prior signed spend authority to a metered charge and issues a portable receipt anyone can verify, without warehousing your logs or sitting in the request path.
QuantZK verifies charge authorities issued by an authorized spend authority. That issuer MAY be the enterprise, a delegated finance authority, a workload-control system, or QuantZK-managed issuance. Managed issuance is commercial, not a protocol requirement.
| Layer | Question |
|---|---|
Authorization (quantzk_charge_authority_v1) | What was allowed? |
| QZR-1 receipt | What was charged? |
| VDI | Why was the decision permitted? |
Do not overload QZR-1 with the full authorization model. The receipt binds a grant; it is not the grant, and it does not by itself prove that the CAS happened.
Charge Authority v1:
- A signed spend authority is bound to the declared pre-execution intent committed by the receipt. Binding uses the fingerprint-committed
authority_idandexecution_intent_digest; continuity compares the fingerprint to the recomputed grant identity; intent digests compare in §4.4 hex form (optional0xstripped). - The canonical charge committed by the QZR-1 billing fingerprint (
billing_verify_fingerprint.expected_charge_micros) satisfies that authority’s applicable constraints. Cap checks MUST use that fingerprint integer only; meter or billing convenience copies MUST NOT backfill a missing or conflicting charge. - Atomic single-use consumption is established only when authenticated consumption evidence is present. In v1, “authenticated” means the verifier trusts the consumption-evidence channel (operator-supplied log / store peek under profile policy), the same trust class as a revocation snapshot. It does not mean an unsigned
consumedAuthorityIdsmap is cryptographically self-authenticating. Classification PASSes only forCONSUMED_BY_THIS_EVENTmatchingauthority_id+event_id+execution_intent_digest. - External request-path enforcement remains an integrator responsibility and is not cryptographically established by Charge Authority v1. No receipt field, attestation, preflight history, or mirror such as
gateway_enforced/path_enforced/may_executemay manufactureMAY_EXECUTEor “path enforced” semantics after the fact. Receipt-time evaluate always reportsmay_execute = false.
Land vs expand
| Surface | Message |
|---|---|
| Website / sales (land) | VERIFY EVERY API CHARGE. Verifiable API billing. |
| Protocol / roadmap (expand) | Authorize every machine spend. Verify every machine charge. |
Keep the homepage on billing. Grow the grant object for spend authority.
Issuance order
ENTERPRISE / DELEGATED / QUANTZK-MANAGED ISSUER
│
▼
CHARGE AUTHORITY v1
"what is allowed?"
signed + independently verifiable
│
▼
LOCAL ENFORCEMENT
gateway / meter / runtime
│
▼
EXECUTION
│
▼
METER EVENT
│
▼
QZR-1
"what was charged?"
│
▼
INDEPENDENT VERIFIER
┌────┴────┐
│ │
AUTHORITY CHARGE
PASS PASS2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
QuantZK is not a mandatory synchronous proxy on every request.
QuantZK does not ensure that only authorized calls reach the vendor API unless the integrator’s gateway/runtime actually gates execution on successful preflight.
Without that enforcement, QuantZK can detect non-conforming evidence afterward. It cannot reach through the network and stop an out-of-band API call. execution_eligible / MAY_EXECUTE is a preflight decision the integrator MUST enforce on the request path for execution exclusivity to be real.
Three evaluation points (normative)
Historical validity, permission to spend now, and attest-time consumption are different decisions.
PREFLIGHT (before paid action) ATTESTATION (after meter) RECEIPT / HISTORICAL
preflightChargeAuthority() POST /billing/attest evaluateQzr1
validate intent binding/trust bind actual meter event
consume_if_available(id,event,intent) verify prior intent consumption
→ execution_eligible / may_execute meter_event_digest + QZR-1 historical_authority_valid
current_authority_status2
3
4
5
6
Authorization and atomic consume occur before execution against execution_intent_digest. Attestation verifies that consumption, binds the actual meter_event_digest, and checks computed_charge_micros <= max_charge_micros. execution_eligible MUST NOT be applied retrospectively after the paid action.
PREFLIGHT / EXECUTION DECISION
preflightChargeAuthority() or POST /api/vdi/billing/preflight. Atomically consumes before the integrator executes the paid call.
signature PASS
intent binding PASS (constraints knowable pre-execution)
current_revocation PASS
authority_trust_mode pinned_roots (open_signature MUST NOT yield execution_eligible unless explicitly opted in)
atomic store present
consume_if_available(authority_id, event_id, execution_intent_digest)
→ execution_eligible / may_execute2
3
4
5
6
7
Generate event_id before the external call. Build quantzk_execution_intent_v1 from fields knowable before execution (no usage_units):
execution_intent_digest =
"0x" || SHA-256( JCS(execution_intent) )2
execution_intent MUST include: event_id, authority_id, tenant_id, contract_version, tariff_id, tariff_version, tariff_digest, unit_price_micros, currency. Optional when constrained on the grant: subject_id, endpoint, vendor_id, model_id, tool_id, cost_center, policy_digest, max_charge_micros.
The consumption row MUST store (authority_id, event_id, execution_intent_digest).
Idempotency:
same authority_id + event_id + execution_intent_digest → IDEMPOTENT
same authority_id + event_id + different execution_intent_digest → FAIL
same authority_id + different event_id → REPLAY FAIL2
3
Preflight does not require usage_units or a post-execution meter event. Variable-consumption workloads (LLM tokens, tool calls) authorize the action under constraints up to max_charge_micros, not a predetermined charge.
A grant is consumed when execution authority is exercised, not when a successful billable outcome is guaranteed. If execution fails after preflight, the grant remains consumed in v1 (retryable reservations are a later primitive).
evaluateAuthorityDecision() is read-only and MUST NOT set execution_eligible / may_execute.
ATTESTATION / CONSUMPTION
POST /api/vdi/billing/attest (and async accept) after the meter event exists:
- Recompute
execution_intent_digestfrom the meter event’s intent-field subset; verify preflight consumed(authority_id, event_id, execution_intent_digest). - Bind grant to the actual meter/tariff/charge (
bindChargeAuthorityToExecution). - Reject if currently revoked.
- Verify
computed_charge_micros <= max_charge_microswhen capped. - Produce QZR-1 binding
meter_event_digestseparately.
meter_event_digest = "0x" || SHA-256( JCS(meter_event) )Attest MUST NOT consume again and MUST NOT report execution_eligible. Missing preflight consumption is REJECT.
RECEIPT / HISTORICAL CHECK
Used by QZR-1 evaluateQzr1. Always context = receipt. may_execute is always false here.
historical_authority_valid PASS
current_authority_status REVOKED
→ historically authorized
→ not currently acceptable2
3
4
QZR-1 Standard MAY PASS a historically bound receipt whose grant is now REVOKED. It MUST NOT be read as permission to spend again.
Canonical payload, digest, and id (normative)
One named structure is the source of every derived value.
canonical_authority_payload
Deep JSON copy of the grant object with these keys removed (MUST NOT be signed, MUST NOT enter the digest):
authority_idauthority_digestsignature.value
Remaining signature metadata (algorithm, domain, kid, public_key) is part of the payload. The signature value is attached after signing.
Keys MUST NOT be present with JSON null. Absence of an optional key means unconstrained (see Optional fields).
Signing message
UTF-8 bytes of the Unicode string:
QZK_CHARGE_AUTHORITY_V1
<JCS(canonical_authority_payload)>2
That is: the exact ASCII domain QZK_CHARGE_AUTHORITY_V1, one LF (U+000A), then RFC-8785-style canonical JSON as implemented by QuantZK JCS (protocol/lib/canonicalize.js). No trailing newline after the JSON.
Ed25519 signs those UTF-8 bytes. A signature valid for another QuantZK artifact type MUST NOT verify as a charge grant.
Digest and id
authority_digest_hex = lowercase hex SHA-256( UTF-8(signing message) )
authority_digest = "0x" || authority_digest_hex // 66 chars: 0x + 64 hex
authority_id = "qza:" || authority_digest_hex // qza: + 64 lowercase hex2
3
Digest algorithm is FIPS 180-4 SHA-256 over the UTF-8 signing message (the same bytes Ed25519 signs). Not SHA-3, not SHAKE, not truncated SHA-256, not a keyed MAC. Implementations MUST:
- exclude
signature.value,authority_id, andauthority_digestfrom the hashed/signed object - use lowercase hex, no Base64
- use the full 32-byte digest (64 hex chars); truncation is invalid
- reject a grant whose
authority_idorauthority_digestdoes not recompute to these values
issuer and issuer_role are inside canonical_authority_payload and are therefore covered by the signature. They are claims, not trust roots.
execution_intent (preflight commitment)
Schema: quantzk_execution_intent_v1. Commits to fields knowable before paid execution. Does not include usage_units, token counts, or other post-execution quantities.
Required keys: schema, event_id, authority_id, tenant_id, contract_version, tariff_id, tariff_version, tariff_digest, unit_price_micros, currency.
Optional (include when constrained on the grant or supplied at preflight): subject_id, endpoint, vendor_id, model_id, tool_id, cost_center, policy_digest, max_charge_micros.
execution_intent_digest = "0x" || SHA-256( JCS(execution_intent) )
meter_event_digest = "0x" || SHA-256( JCS(meter_event) ) // after execution2
At attest, recompute execution_intent from the meter event’s intent-field subset (executionIntentFromMeterEvent) and verify it matches the consumption row. Emit execution_intent and execution_intent_digest on the QZR-1 envelope and on billing_verify_fingerprint. Receipt evaluation MUST use the fingerprint expected_charge_micros for max_charge_micros (the hashed charge), MUST FAIL if billing.expected_charge_micros disagrees with the fingerprint, MUST FAIL if fingerprint.authority_id disagrees with the embedded grant, and MUST FAIL if execution_intent_digest disagrees across envelope / billing / fingerprint.
Trust roots (normative)
issuer and issuer_role are claims made by the signed authority object. They acquire trust significance only through an accepted issuer key and an explicit trust mode. issuer_role: enterprise cannot by itself establish enterprise authority.
Trust MUST NOT be inferred from whether authorized_authority_public_keys happens to be empty.
authority_trust_mode | Meaning |
|---|---|
open_signature | Cryptographic signature validity only. The allow-list is ignored. Default. |
pinned_roots | The grant signature.public_key MUST be in authorized_authority_public_keys. An empty list authorizes nobody. |
Profile guidance (not additional modes):
| Profile | Typical authority trust |
|---|---|
| Minimal / receipt | Grant MAY be NOT_CHECKED; open_signature is useful for “internally valid but unanchored” |
| Standard receipt | Binding as specified; open_signature unless the profile sets pinned_roots |
Execution / MAY_EXECUTE | pinned_roots required. open_signature MUST NOT yield may_execute unless allow_open_signature_may_execute is explicitly true |
| Strict | pinned_roots + fresh attestation revocation; authority current-revocation remains a separate snapshot |
QZR-1 evaluate reads trustRoots.authority_trust_mode. If omitted, open_signature applies even when the key array is non-empty; pinning requires the mode. That default is for receipt evaluation only.
Atomic single-use consumption (normative)
v1 usage_mode = single_use is operationally enforced at preflight by:
consume_if_available(authority_id, event_id, execution_intent_digest)State transition (compare-and-set before paid execution):
AVAILABLE
│
│ atomic compare-and-set at preflight
▼
CONSUMED_BY_THIS_EVENT2
3
4
5
PostgreSQL: INSERT … ON CONFLICT (authority_id) DO NOTHING, then read existing row to distinguish idempotent vs replay vs digest mismatch.
Recommended lifecycle (variable consumption):
signed grant
↓
preflightChargeAuthority (atomic consume on execution_intent_digest)
↓
execution_eligible
↓
paid action (usage emerges)
↓
meter event → meter_event_digest
↓
attest (verify intent consumption + bind actual charge ≤ max)
↓
QZR-1 binds charge_authority + execution_intent_digest + meter_event_digest2
3
4
5
6
7
8
9
10
11
12
13
A grant is consumed when execution authority is exercised, not when a successful billable outcome is guaranteed. If execution fails after preflight, the grant remains consumed. From a security perspective this is fail-closed on spend authorization. Operationally it is a liveness / usability failure (authority consumed without a billable result). v1 does not release or retry that grant.
Security properties and non-properties (normative)
This section is normative. Reviewers MUST treat it as the claim boundary for Charge Authority v1.
Frozen core promise
- A signed spend authority is bound to the declared pre-execution intent committed by the receipt. Binding uses the fingerprint-committed
authority_idandexecution_intent_digest; continuity compares the fingerprint to the recomputed grant identity; intent digests compare in §4.4 hex form (optional0xstripped). - The canonical charge committed by the QZR-1 billing fingerprint (
billing_verify_fingerprint.expected_charge_micros) satisfies that authority’s applicable constraints. Cap checks MUST use that fingerprint integer only; meter or billing convenience copies MUST NOT backfill a missing or conflicting charge. - Atomic single-use consumption is established only when authenticated consumption evidence is present. In v1, “authenticated” means the verifier trusts the consumption-evidence channel (operator-supplied log / store peek under profile policy), the same trust class as a revocation snapshot. It does not mean an unsigned
consumedAuthorityIdsmap is cryptographically self-authenticating. Classification PASSes only forCONSUMED_BY_THIS_EVENTmatchingauthority_id+event_id+execution_intent_digest. - External request-path enforcement remains an integrator responsibility and is not cryptographically established by Charge Authority v1. No receipt field, attestation, preflight history, or mirror such as
gateway_enforced/path_enforced/may_executemay manufactureMAY_EXECUTEor “path enforced” semantics after the fact. Receipt-time evaluate always reportsmay_execute = false.
Cryptographically bind authority → intent → meter → charge. Operationally enforce single-use consumption. Explicitly delegate request-path enforcement to the integrator. Never claim more than the selected evidence profile establishes.
Committed-value dominance. No security decision may be made from an uncommitted mirror when a cryptographically committed representation of the same semantic fact exists. Conflicting representations fail verification. JSON null and "" are present-and-invalid, not absence. Registry: QZR-1 §4.4.
Continuity chain
signed charge_authority
↓
execution_intent_digest (pre-execution; on QZR-1 wire)
↓
consume_if_available(authority_id, event_id, intent_digest)
↓
meter_event_digest (post-execution)
↓
expected_charge_micros
↓
QZR-1 / Phase-2 binding (meter commitments; not in-circuit intent)2
3
4
5
6
7
8
9
10
11
Portable/offline QZR-1 without consumption evidence can establish:
charge_authority
↓
execution_intent_digest
↓
meter_event projection matches intent
↓
meter_event_digest
↓
expected_charge_micros
↓
QZR-12
3
4
5
6
7
8
9
10
11
It cannot independently prove that the CAS happened merely because execution_intent_digest is embedded. That requires authority_consumption_check = PASS from authenticated consumption evidence.
| Link | Enforcement |
|---|---|
| Grant authenticity | Cryptographic / Ed25519 |
| Authority identity / trust | Trust-root policy (pinned_roots at execution; profile-selected at receipt) |
| Intent integrity | Cryptographic digest (execution_intent_digest on the QZR-1 wire) |
| Single-use grant consumption | Atomic operational store at preflight; receipt-time check against a trusted consumption-evidence channel |
| Intent → meter consistency | Verifier logic (execution_intent_binding) |
| Meter integrity | QZR-1 fingerprint + meter_event_digest |
| Charge ≤ authority cap | Verifier logic (max_charge_micros) |
| Phase-2 predicates | Circuit, where enabled (meter public commitments; not intent digest) |
| Current revocation | Snapshot / trust state |
| Actual request-path gating | Integrator (required for MAY_EXECUTE semantics) |
| Meter truthfulness (that reported units equal physical usage) | Out of scope |
| Reservation / settlement / release | Out of scope |
TOCTOU and gateway enforcement
Preflight atomically claims the grant for an execution intent. It does not create a cryptographic lease on the vendor API.
QuantZK does not ensure that only authorized calls reach the vendor API unless the integrator’s gateway/runtime actually gates execution on successful preflight.
QuantZK provides: grant validity, intent commitment, atomic single-use claim, post-execution constraint verification, portable charge evidence.
The integrator provides: successful preflight → actual request-path enforcement.
Without that enforcement, QuantZK can detect non-conforming evidence afterward. It cannot stop an out-of-band API call.
Windows that remain after preflight CAS:
- Integrator executes without preflight, or executes a different action than the intent.
- Grant revoked after execution started (attest fails; sunk cost possible).
event_timestampwindow is checked at attest, not preflight.
Consumption evidence vs authority binding
These are different assurance properties. Do not collapse them.
authority PASS | FAIL | NOT_CHECKED // cryptographic + constraint binding
execution_intent_binding PASS | FAIL | NOT_CHECKED // declared digest matches meter projection
authority_consumption NOT_CHECKED | AVAILABLE | CONSUMED_BY_THIS_EVENT | CONSUMED_BY_OTHER_EVENT
authority_consumption_check PASS | FAIL | NOT_CHECKED2
3
4
What “authenticated consumption evidence” means in v1 (normative).
Receipt-time Claim 3 does not embed a portable signed ConsumptionEvidence object in the QZR-1 envelope. The verifier receives consumption state through a channel the profile trusts (for example an integrity-trusted store peek, or an operator-supplied log under the same policy class as revocation snapshots). Under that channel:
| Evidence | Receipt authority_consumption | authority_consumption_check |
|---|---|---|
Channel absent (undefined / omitted) | NOT_CHECKED | NOT_CHECKED |
| Empty log | AVAILABLE | FAIL |
Row for this authority_id + event_id + matching execution_intent_digest | CONSUMED_BY_THIS_EVENT | PASS |
Wrong authority_id / event / intent digest, or bare event_id when intent is required | AVAILABLE or CONSUMED_BY_OTHER_EVENT | FAIL |
A bare event_id string MUST NOT classify as CONSUMED_BY_THIS_EVENT when an execution_intent_digest is expected. Portable, domain-separated, signature-verified consumption envelopes are out of scope for v1; claiming them would be a new wire artifact.
| Profile | Consumption |
|---|---|
| QZR-1 Standard historical receipt | authority_consumption_check ∈ {PASS, NOT_CHECKED}; FAIL fails Standard |
| Enterprise enforcement profile | MAY require authority_consumption_check == PASS |
Execution / execution_eligible | Atomic consume required before MAY_EXECUTE |
A portable receipt with authority_consumption_check = NOT_CHECKED is cryptographically bound to a prior authority. It is not proof that the authority was consumed exactly once.
v1 limitations (explicit)
- No
reserve → authorize → execute → settle → release. - No cryptographic proof of gateway path enforcement.
- No in-circuit
execution_intent_digestbinding. - No offline proof of single-use consumption unless authenticated consumption evidence is supplied.
- Crash after consume is fail-closed on authorization and a liveness/usability failure operationally.
Charge Authority v1 freeze boundary
Claims 1–4 are the frozen v1 claim set:
- Authority ↔ committed execution intent continuity
- Fingerprint-committed charge ↔ authority constraints
- Consumption PASS only from a trusted evidence channel (not a self-authenticating unsigned map)
- Request-path enforcement remains outside the cryptographic claim
Do not add new semantic claims inside v1. A portable signed ConsumptionEvidence envelope (upgrading Claim 3 from trusted-channel to cryptographic evidence) is the first deliberately scoped v1.1 candidate.
Time (normative)
All grant timestamps (issued_at, valid_from, valid_until) MUST be integer Unix seconds (non-negative). Fractional numbers are invalid. JSON numbers MUST be integers; implementations MUST reject 1700000000.5.
Well-formed grant:
issued_at <= valid_from <= valid_untilLet s be permitted clock skew in seconds (default 60, overridable via trust-root authority_clock_skew_seconds). Meter event_timestamp is converted to integer Unix seconds (ISO-8601 is floored to seconds). Then both:
event_timestamp >= valid_from - s
event_timestamp <= valid_until + s2
and independently:
event_timestamp >= issued_at - sThe independent predating rule is required even when valid_from equals issued_at (they can diverge). This is consistency of authenticated timestamps, not proof that an untrusted source clock is correct.
max_charge_micros (normative)
When the key is present:
computed_charge_micros <= max_charge_microscomputed_charge_micros is the same canonical integer bound into QZR-1 as fingerprint expected_charge_micros. It is not a floating-point price, not a re-derived invoice unless that derivation already produced this integer, and not billing.expected_charge_micros or meter_event.expected_charge_micros when those disagree with or substitute for the fingerprint. At receipt bind, if max_charge_micros is present and the fingerprint charge is absent or not a safe integer, verification FAILs (no fallback, no string coercion).
Both values MUST be integers in 0 … 2^53-1 (Number.MAX_SAFE_INTEGER). Overflow or non-integers → FAIL (QZA_ERR_MAX_CHARGE). No multiplication/division is performed at the grant bound; the cap applies to the already-canonical settled charge. Taxes, credits, and discounts are outside this v1 cap unless already folded into expected_charge_micros.
This grant cap is distinct from tariff_snapshot.max_charge_micros.
Optional fields: absence semantics (normative)
For subject_id, endpoint, vendor_id, model_id, tool_id, cost_center, max_charge_micros, policy_digest:
- Key absent → unconstrained by this grant.
- JSON
nullis not absence. Present-and-null is invalid. - Empty string is not absence. Present-and-
""is invalid.
Issuance MUST omit unconstrained keys rather than emit null or "".
Consumption state machine (normative)
v1 grants are single-use by declaration:
| Field | v1 rule |
|---|---|
usage_mode | MUST be single_use |
authority_id | Unique (qza: + SHA-256 hex as above) |
nonce | Unique, always issued |
Underlying state authority_consumption:
| State | Meaning |
|---|---|
NOT_CHECKED | No consumption log supplied, or binding already failed |
AVAILABLE | Log present; this authority_id is not recorded as consumed |
CONSUMED_BY_THIS_EVENT | Log maps this authority_id to this meter event_id |
CONSUMED_BY_OTHER_EVENT | Log maps this authority_id to a different event (or consumed with unknown event) |
Do not collapse AVAILABLE with CONSUMED_BY_THIS_EVENT. A verifier reading an existing receipt MUST NOT treat “the grant has never been consumed” as “this receipt properly consumed it.”
Derived checks:
| Context | PASS | FAIL |
|---|---|---|
| Execution | AVAILABLE | CONSUMED_BY_THIS_EVENT, CONSUMED_BY_OTHER_EVENT |
| Receipt | CONSUMED_BY_THIS_EVENT | AVAILABLE, CONSUMED_BY_OTHER_EVENT |
NOT_CHECKED is permitted when no log is supplied (receipt-time). QZR-1 Standard fails closed on authority_consumption_check = FAIL (including receipt + AVAILABLE).
Execution-time AVAILABLE is necessary but not sufficient for MAY_EXECUTE (see Atomic single-use consumption).
Do not treat a signed nonce as a proof of non-replay. Reusable, time-window-unlimited, and cumulative-cap modes are not specified in v1.
Who signs
| Field | Meaning |
|---|---|
issuer | Display-name claim (not a trust root) |
issuer_role | Claim: self_issued | enterprise | delegated_finance | workload_control | quantzk_managed |
issuer_kid | Key id (also signature.kid) |
signature | Ed25519 over the domain-separated canonical_authority_payload |
delegation_chain | Optional; not verified in v1 |
API POST /billing/authorize sets issuer_role: quantzk_managed when QuantZK’s key signs. Local SDK signing defaults to self_issued.
Revocation
Historically valid authorization ≠ currently acceptable authorization.
When an authority revocation snapshot is supplied (revokedAuthorityIds / revokedAuthorityKids; not the attestation revokedKids list):
| Status | Meaning |
|---|---|
historical_authority_valid | Binding/signature were valid at evaluation |
authority_revocation | PASS / FAIL membership in the snapshot |
current_authority_status | CLEAR / REVOKED / NOT_CHECKED |
Without a snapshot: authority_revocation = NOT_CHECKED. Receipt-time Standard does not fail solely because current authority status is NOT_CHECKED or REVOKED. Execution-time MUST fail closed on REVOKED.
What authority: PASS means (receipt-time)
See AUTHORITY_PASS_CLAIMS in @quantzk/vdi-billing. Receipt-time authority: PASS is cryptographic + constraint binding. It is not MAY EXECUTE.
What it does not mean
See AUTHORITY_NON_CLAIMS: permission to execute a new paid action from a receipt check alone, execution_eligible / MAY_EXECUTE under open_signature or a non-atomic view, that a portable receipt proves atomic consumption when authority_consumption_check is NOT_CHECKED, that a successful billable outcome is guaranteed after consumption, budget reservation or retryable spend after failed execution, path enforcement, in-circuit intent binding, clock-source proof, current non-revocation without a snapshot, delegation-chain verify, that issuer_role confers trust, gateway controls.
reserve → authorize → execute → settle → release is a later primitive. v1 does not implement it.
Canonical fields
Wire names are snake_case integers. SDK maps camelCase 1:1:
| SDK | Wire |
|---|---|
tenantId | tenant_id |
contractVersion | contract_version |
unitPriceMicros | unit_price_micros |
currency | currency |
Do not use IEEE-754 price: 0.00012 as the canonical API. unitPriceMicros: 120 only.
Optional (omit when unconstrained): subject_id, endpoint, vendor_id / model_id / tool_id, cost_center, max_charge_micros, policy_digest, delegated_authority, delegation_chain.
Modes
| Mode | Behavior |
|---|---|
| Default | Attest without charge_authority → authority = NOT_CHECKED |
| Recommended | authorize → preflight → execute → record({ authority }) (same execution-intent fields at preflight and attest) |
| Enforced | VDI_BILLING_REQUIRE_AUTHORITY=true rejects attest without a grant |
POST /billing/preflight atomically consumes before execution. POST /billing/attest verifies that consumption. Response includes execution_eligible (preferred) and may_execute (alias).
API / SDK
const grant = await qzk.authorize({
tenantId: 'cus_acme',
unitPriceMicros: 120,
currency: 'USD',
subjectId: 'agent_814',
endpoint: '/v1/responses',
modelId: 'gpt-x',
maxChargeMicros: 5_000_000,
});
const gate = await qzk.preflight({
authority: grant,
eventId: 'evt_1',
tenantId: 'cus_acme',
endpoint: '/v1/responses',
modelId: 'gpt-x',
// no units; usage is unknown until after execution
});
if (!gate.execution_eligible) throw new Error('not authorized to spend');
// …execute the paid call; record actual usage…
const receipt = await qzk.record({
eventId: 'evt_1',
tenantId: 'cus_acme',
endpoint: '/v1/responses',
modelId: 'gpt-x',
units: 5678,
unitPriceMicros: 120,
authority: grant,
});2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
HTTP: POST /api/vdi/billing/authorize → POST /api/vdi/billing/preflight → execute → POST /api/vdi/billing/attest with charge_authority.
Library: preflightChargeAuthority(), verifyChargeAuthorityConsumption(), buildExecutionIntent(), chargeAuthorityExecutionIntentDigestHex(), chargeAuthorityEventDigestHex() (meter), and read-only evaluateAuthorityDecision() for receipt-time checks.
Spec
Normative binding rules: QZR-1 §4.3.
