alexpaynex 599771e0ae Task #27: Atomic free-tier gate — complete, all reviewer issues fixed
== All fixed issues ==

1. /api/estimate pool mutation (fixed)
   - Added decideDryRun(): non-mutating read-only free-tier preview
   - /api/estimate uses decideDryRun(); pool never debited by estimate calls

2. Free-path passes actual debited amount not estimate (fixed)
   - In runEvalInBackground free path: uses ftDecision.absorbSats (actual pool debit)
   - DB absorbedSats column set to actual debited sats, not breakdown.amountSats
   - runWorkInBackground receives reservedAbsorbed = actual pool debit

3. decide() free branch: downgrade to partial if atomic debit < estimated (fixed)
   - After _atomicPoolDebit, if debited < estimatedSats (pool raced):
     - Release the partial debit back to pool
     - Return serve="partial" with advisory amounts (re-reserved at payment time)
   - Only returns serve="free" with chargeSats=0 if debited >= estimatedSats

4. Reservation leak on pre-work failure (fixed)
   - Free path wrapped in inner try/catch around DB update + setImmediate
   - If setup fails after pool debit: releaseReservation() called; throws so outer
     catch sets job to failed state

5. Partial-job pool-drained at payment => fail with refund (implemented)
   - reservePartialGrant() = 0 at payment time => job.state = failed
   - refundState = pending, refundAmountSats = workAmountSats (user gets money back)
   - Work does NOT execute under discounted terms without pool backing

6. Partial-job refund math corrected (fixed)
   - actualUserChargeSats = max(0, actualTotalCostSats - partialAbsorbSats)
   - refund = workAmountSats - actualUserChargeSats

7. Grant audit reconciliation (fixed)
   - actualAbsorbed = min(actualTotalCostSats, reservedAbsorbed)
   - over-reservation returned to pool atomically in recordGrant()
   - Audit log and daily counter reflect actual absorbed sats

New API: decideDryRun(), reservePartialGrant(), releaseReservation()
New recordGrant signature: (pubkey, hash, actualAbsorbed, reservedAbsorbed)
2026-03-19 17:25:13 +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%