The Stripe402Store interface defines the contract for persistence backends in stripe402. Any class implementing this interface can be used as the store in Stripe402ServerConfig.
Look up a client by their HMAC-derived identifier.
Parameter
Type
Description
clientId
string
64-character hex string from deriveClientId().
Returns: The ClientRecord if found, or null if no client exists with that ID.
createClient(record: ClientRecord): Promise<void>
Create a new client record. If a record with the same clientId already exists, implementations should either ignore the duplicate (idempotent) or throw.
Parameter
Type
Description
record
ClientRecord
The full client record to create.
Implementations:
RedisStore: Uses hset — overwrites if exists
PostgresStore: Uses INSERT ... ON CONFLICT DO NOTHING — idempotent
Atomically deduct from a client's balance. This method must be atomic — it must check that balance >= amount and deduct in a single operation to prevent double-spending under concurrent requests.
Parameter
Type
Description
clientId
string
The client identifier.
amount
number
Amount to deduct in units.
Returns:
number — the new balance after deduction, if balance >= amount
null — if the balance is insufficient (no deduction was made)
Atomicity requirement: This is the most critical method. Without atomicity, two concurrent requests could both read the same balance and both deduct, resulting in a negative balance. Implementations must use database-level guarantees:
Record a transaction for audit logging. This method is optional — the ? in the interface means stores can omit it entirely.
Parameter
Type
Description
transaction
TransactionRecord
The transaction to record.
The middleware checks if (config.store.recordTransaction) before calling this method. Stores that don't need audit logging can simply not implement it.
Both built-in stores (RedisStore and PostgresStore) implement this method.
Implementing a Custom Store
See the Custom Store Backend guide for a walkthrough of building your own Stripe402Store implementation.