- Without an
on_failurecallback, a transient background check failure (network outage, timeout,rate_limited,system_error,no_credits, ...) no longer ends the process. The SDK prints one line to stderr,AuthForge: background check failed (<code>); retrying next interval, keeps the session and checks in again on the next interval. Previously a brief outage killed any app that enabled online check-ins without setting a callback. - Unchanged: without a callback, definitive failures (including the
session_expireda transient failure becomes once the session TTL has passed) and failedlogin()calls still callos._exit(1).
- The README and
AGENTS.mdexamples no longer callos._exit(1)fromon_failure. They set athreading.Eventthat the main thread checks so it can save work and exit, mention_thread.interrupt_main()for blocked main threads, and keepos._exitas a last resort after saving.
on_failure("heartbeat_failed", exc)now always receives anAuthForgeError(aValueErrorsubclass) withexc.code,exc.transientandexc.fatal. For server codesstr(exc)equals the code.is_transient_error()andDEFINITIVE_ERROR_CODESare exported;TRANSIENT_ERROR_CODESlists the named transient codes for reference.- Classification: only
revoked,expired,hwid_mismatch,blocked,session_expired,malformed_request,app_disabled,invalid_appandsignature_mismatchare definitive. Everything else is transient, includingno_credits,demo_quota_exceeded,app_burn_cap_reached,bad_request,invalid_key, everyhttp_error_<status>and unknown codes. - Transient heartbeat failures are reported and background checks keep running on the next interval. Previously the loop stopped after any failure. After the session TTL passes, the next transient failure is reported as a definitive
session_expired; grace-period expiry also reportssession_expired. - Definitive heartbeat failures clear the stored session (as
logout()does) and stop background checks beforeon_failureruns. Previously the session stayed authenticated. - New code
unexpected_response(transient): a failed check-in whose body is not a JSON object with"status": "failed"and a non-emptyerrorstring. The message includes the rawstatusanderror. - Request retries: only
rate_limited, or HTTP 429 with no error code, is retried (after 2s, then 5s).no_credits,demo_quota_exceededandapp_burn_cap_reachedon HTTP 429 are no longer retried. This also applies tologin()andvalidate_license(). - Heartbeat network failures no longer also fire
on_failure("network_error", ...); they are reported once asheartbeat_failedwith codenetwork_errorortimeout. - Server codes this SDK doesn't know are passed through as-is instead of becoming
unknown_error(also invalidate_license()results). - HTTP errors with a non-JSON body (
http_error_<status>), network failures and unparseable responses now raiseAuthForgeErrorinstead ofRuntimeError/ plainValueError. on_failureruns with no SDK lock held, so it may calllogout(),is_authenticated()orlogin(). A check-in still in flight duringlogout()orlogin()is discarded instead of restoring the old session.