feat(core): burn windows, and the rules that make an allowance mean something

The unit is one second of a reference session — baseline size, baseline card,
running alone, on hardware we own. Every factor is a multiple of that, so an
allowance is measured in time and a bar prints the stored number instead of
converting into it. Integers throughout.

Three rolling windows, one function. A counter is stored beside the time it was
last written, and a counter whose timestamp falls outside its window reads as
zero — so the reset is implied by the clock and nothing has to run for a window
to roll clear. No scheduled job to misfire, and no race between a reset and a
write landing together. The same rule on the write side is one statement rather
than a read followed by a decision.

The check is pure, and it is the same arithmetic the meter draws from. The
complaint about usage limits is almost never the limit, it is being surprised
by one, and two implementations that agree today are how a full bar and a
refusal start disagreeing.

Two rules on the allowances, enforced rather than remembered:

- A window's allowance must exceed the window itself. Because the windows roll,
  one uninterrupted session asymptotes at exactly the window length, so an
  allowance at or below it is a wall that someone playing alone will meet.
- Each longer allowance must be under what the shorter window already permits,
  or it can never be reached — a number that looks like a limit, reads like a
  promise, and never once fires.

Allowances are configuration rather than constants, because they will be
retuned against real burn far more often than this code changes, and a rate
that needs a deploy is a rate that stays wrong until the next one. The shipped
set is explicitly a placeholder: coherent enough to test against, not a pricing
decision.
This commit is contained in:
Wanjohi
2026-09-18 23:44:00 +03:00
parent 15631f5d25
commit b819367a09
5 changed files with 551 additions and 0 deletions

View File

@@ -27,6 +27,15 @@ export namespace Env {
*/
AUTH_INTERNAL_URL: z.string().optional(),
/**
* Burn allowances per plan, as JSON. Unset takes the placeholder set.
*
* Configuration rather than constants because these are retuned against
* real burn far more often than the code that reads them changes, and a
* rate that needs a deploy is a rate that stays wrong until the next one.
*/
BURN_LIMITS: z.string().optional(),
DATABASE_URL: z.string().optional()
});