tollgate-store 0.30.2

Storage abstraction for tollgate: LeaseAllocator, SnapshotSource, and UsageSink traits, plus the in-memory reference implementation.
Documentation

tollgate-store

The storage contract of Tollgate, and MemoryStore, the reference implementation of it.

Narrow traits separate the data plane from lifecycle authority:

  • LeaseAllocator atomically debits an account's balance into fenced, TTL-bounded leases, and settles them by release or expiry reclaim.
  • SnapshotSource fetches compiled account snapshots and subscribes to pushes.
  • UsageSink ingests usage events in idempotent, fencing-checked batches.
  • KeySource serves validated, revisioned pages of active credential digests.
  • AdminStore and KeyDirectory hold administrative and credential-lifecycle authority, which instances do not need.

Every method takes now as an argument: a store never reads a clock, so backends are deterministic under test and the clock decision lives in one place.

The reference implementation

MemoryStore proves the traits are not shaped like any particular database, runs the correctness suite without infrastructure, and documents the settlement rules a real backend must reproduce. tollgate-store-postgres reproduces them exactly, and a mirrored test suite holds the two to one contract.

use jiff::{SignedDuration, Timestamp};
use tollgate_core::{AccountId, AccountStatus, CapacityClass, CostUnits};
use tollgate_store::{AccountConfig, AdminStore, GrantPolicy, LeaseAllocator, MemoryStore};

# #[tokio::main(flavor = "current_thread")]
# async fn main() {
let store = MemoryStore::new(GrantPolicy::default()).expect("valid policy");
AdminStore::create_account(
    &*store,
    AccountConfig {
        account_id: AccountId(1),
        initial_balance: CostUnits(1_000),
        status: AccountStatus::Active,
        capacity_class: CapacityClass::Assured,
    },
)
.await
.expect("new account");

// A fenced lease for an instance to spend locally for thirty seconds.
let now = Timestamp::from_second(1_755_600_000).unwrap();
let allocation = store
    .acquire(AccountId(1), CostUnits(100), SignedDuration::from_secs(30), now)
    .await
    .expect("funded");
assert_eq!(allocation.grant.units, CostUnits(100));

// Every unit is accounted for: deposited = balance + active grants + settled
// usage + settlement loss + expired (plus recorded overage on the left).
let ledger = store.conservation(AccountId(1)).expect("known account");
assert_eq!(ledger.balance, CostUnits(900));
assert!(ledger.holds());
# }

Features

  • wire: the HTTP wire contract shared by tollgate-server and tollgate-client's HTTP transport. Off by default, so store-only consumers skip serde.

Contract

The settlement rules and the conservation equation are specified in INVARIANTS.md; docs/USAGE_ACCOUNTING.md covers batch rejection semantics, and docs/LEASE_OWNERSHIP.md lease ownership.

License

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