* feat: out-of-process usage-snapshot builder (Phase 1)
Move all usage-tab compute off the run-serving HTTP process (the #1434 bug
class). Read path is now a pure cache read with a typed computing placeholder
on cold miss; a dedicated usage_snapshot graph + global ~10min cron rebuild
every period's snapshot out-of-process, wrapped in asyncio.timeout and gated by
USAGE_SNAPSHOT_CRON_ENABLED. Lifespan makes one fire-and-forget scheduling call,
never a retained/looping task.
* fix: address PR review on usage-snapshot builder
- admin guard on /admin/usage/rebuild (was any logged-in user)
- cap lifespan loopback calls with asyncio.timeout(5) so a startup hang
can't block boot
- memoize cron registration so steady-state requests skip the loopback
check; reap duplicate crons from concurrent-replica races
- thread the computing flag through the usage payload too