tollgate-core 0.30.1

Zero-I/O, clock-free domain layer for quota admission and accounting: cost tables, account snapshots, fenced local leases, and the reservation state machine.
Documentation
# tollgate-core

The zero-I/O domain layer of [Tollgate](https://github.com/MorphIQ-Labs/tollgate):
cost tables, compiled account snapshots, fenced local leases, and the
reservation state machine that decides what a request is charged.

Every operation is a function of its arguments. There is no I/O, no clock read
(callers pass `now`), no blocking lock, and cost arithmetic is checked, never
wrapping. Unknown, expired, exhausted, or overflowing states deny; there is no
slower path to fall back to. That is what lets the layer sit inside a request
whose whole budget is a few microseconds.

## Where it sits

Tollgate has two planes. The request path is this crate and
[`tollgate-admission`](https://crates.io/crates/tollgate-admission); the
control plane is [`tollgate-client`](https://crates.io/crates/tollgate-client),
[`tollgate-server`](https://crates.io/crates/tollgate-server), and a
[`tollgate-store`](https://crates.io/crates/tollgate-store) backend. Most
services embed Tollgate through `tollgate-admission` and `tollgate-client`;
this crate is the vocabulary they share.

## Charging a request

A snapshot admits the account, a cost table quotes the work, a lease reserves
the units, and the reservation either commits at execution start, charging the
full quote whatever the outcome, or is cancelled before execution for zero.

```rust
use std::sync::Arc;

use jiff::Timestamp;
use tollgate_core::{
    AccountId, AccountSnapshot, AccountStatus, CancelOutcome, CommitFunding, CostTable,
    CostUnits, FencingToken, Generation, LeaseGrant, LeaseId, LocalLease, OpIndex,
    PermissionBits, Reservation, ResolvedLimits,
};

// The embedder's operations, as dense indexes into the cost table.
enum Op {
    Price,
    Greeks,
}

impl OpIndex for Op {
    fn index(&self) -> usize {
        match self {
            Op::Price => 0,
            Op::Greeks => 1,
        }
    }
}

let now = Timestamp::from_second(1_755_600_000).unwrap();
let expires = Timestamp::from_second(1_755_600_060).unwrap();

// One unit fixed per request, plus a per-item weight per operation.
let table = Arc::new(
    CostTable::builder(CostUnits(1), CostUnits(1))
        .weight(&Op::Price, CostUnits(1))
        .weight(&Op::Greeks, CostUnits(5))
        .build(),
);
let snapshot = AccountSnapshot::builder(
    AccountId(1),
    Generation(1),
    AccountStatus::Active,
    expires,
    PermissionBits::bit(0),
    ResolvedLimits::new(1_024),
    Arc::clone(&table),
)
.build();

// A lease the control plane granted: 100 units, spent locally.
let lease = Arc::new(LocalLease::new(
    LeaseGrant {
        lease_id: LeaseId(1),
        account_id: AccountId(1),
        fencing_token: FencingToken(1),
        units: CostUnits(100),
        expires_at: expires,
    },
    CostUnits(10),
));

snapshot.admit(now, PermissionBits::bit(0)).expect("active, fresh, permitted");
let quote = table.quote(&Op::Greeks, 4).expect("known operation");
assert_eq!(quote.total, CostUnits(21)); // 1 fixed + 5 per item × 4

// Admission debits the lease, but the charge is only pending.
let reservation = Reservation::reserve(&lease, quote.total, now).expect("funded");
assert_eq!(lease.remaining(), CostUnits(79));

// Execution start commits the full quote, for success, failure or timeout.
let charged = reservation
    .commit_at_execution_start(now, CommitFunding::LeaseOnly)
    .expect("inside the lease window");
assert_eq!(charged, CostUnits(21));

// A request that ends before execution is released for zero instead.
let early = Reservation::reserve(&lease, CostUnits(5), now).expect("funded");
assert!(matches!(early.cancel(), CancelOutcome::ZeroCharged));
assert_eq!(lease.remaining(), CostUnits(79));
```

Commit and cancel race on one atomic transition, so exactly one wins.

## Features

- `serde`: `Serialize`/`Deserialize` for the wire-visible types: snapshots
  and cost tables, lease grants, usage events, deny reasons, budgets,
  identifiers, and units. Off by default.

## Contract

The behaviour above is specified in
[`INVARIANTS.md`](https://github.com/MorphIQ-Labs/tollgate/blob/main/INVARIANTS.md),
where each invariant names the tests that enforce it, and parts are modelled in
Lean under [`formal/lean`](https://github.com/MorphIQ-Labs/tollgate/tree/main/formal/lean).
Rationale and history are in
[`docs/DESIGN.md`](https://github.com/MorphIQ-Labs/tollgate/blob/main/docs/DESIGN.md).

## License

MIT OR Apache-2.0, at your option. Tollgate is a product of MorphIQ Labs, a
trade name of Prophetizo LLC.