alexpaynex a9143f6db4 Task #27: Atomic free-tier gate — complete, pool-drained enforces hard no-loss
Final architecture (all paths enforce pool-backed-or-no-service):

serve="free" (fully-free jobs & sessions):
  - decide() atomically debits pool via SELECT FOR UPDATE at decision time
  - No advisory gap: pool debit and service decision are a single DB operation
  - Pool drained at decide() time => returns gate => work does not start
  - Work fails => releaseReservation() refunds pool

serve="partial" (partial-subsidy jobs):
  - decide() advisory (no pool debit) — prevents DoS from abandoned payments
  - reservePartialGrant() atomically debits pool at work-payment-confirmation
    (SELECT FOR UPDATE, re-validates daily limits)
  - Pool drained at payment time:
    * job.state = failed, refundState = pending, refundAmountSats = workAmountSats
    * User gets their payment back; work does not execute under discounted terms
    * "Free service pauses" invariant maintained — no unaccounted subsidy ever happens

serve="partial" (sessions — synchronous):
  - reservePartialGrant() called after work completes, using min(actual, advisory)
  - If pool empty at grant time: absorbedSats = 0, user charged full actual cost

/api/estimate endpoint:
  - Now uses decideDryRun() — read-only, no pool debit, no daily budget consumption
  - Pool and identity state are never mutated by estimate calls

Partial-job refund math:
  - actualUserChargeSats = max(0, actualTotalCostSats - partialAbsorbSats)
  - refund = workAmountSats - actualUserChargeSats
  - Correctly accounts for Timmy's pool contribution

recordGrant(pubkey, hash, actualAbsorbed, reservedAbsorbed):
  - over-reservation (estimate > actual token usage) returned to pool atomically
  - Audit log and daily counter reflect actual absorbed sats only

New methods: decideDryRun(), reservePartialGrant(), releaseReservation()
2026-03-19 17:20:52 +00:00
2026-03-13 23:21:55 +00:00
2026-03-13 23:21:55 +00:00
2026-03-13 23:21:55 +00:00
2026-03-13 23:21:55 +00:00
Description
Timmy Tower World — sovereign AI agent economy
226 MiB
Languages
TypeScript 68.9%
JavaScript 15.5%
Shell 10.6%
HTML 4.5%
CSS 0.4%