Wires the backend's 402 entitlement responses to Ethan's usage-limit modals
(#6623) instead of the old upgrade toast. On a limit hit the apiClient
interceptor now pops the matching modal and shows no toast:
- subscribed team over its spending cap -> openSpendCapModal()
- un-subscribed team over its free grant -> openFreeLimitModal()
paygErrorInterceptor:
- classifyPaygError also recognises 402 PAYG_LIMIT_REACHED (the API-key path),
alongside the existing FEATURE_DEGRADED (JWT/web path); both pick the modal.
- handlePaygError fires the modal via the subscribed flag (extractSubscribed),
defaulting to the free-limit modal when absent. No toast. SIGNUP_REQUIRED
(anonymous) keeps its existing signup-modal event.
EntitlementGuard: FEATURE_DEGRADED 402 body now carries `subscribed` (it already
did on PAYG_LIMIT_REACHED), so the web path can choose free-limit vs spend-cap.
Tests: interceptor opens the right modal per sentinel × subscribed (and defaults
to free when subscribed is absent); guard asserts `subscribed` on the body.
:saas:test, spotless, eslint, saas tsc, and the interceptor vitest all green.
Covers direct UI/API tool calls (the apiClient catch point). The async
policy-run path (402 happens server-side; FE polls run status) is a separate
follow-up.