get_event_loop() is deprecated on Python 3.11+ when there is no running
loop and is slated to change behaviour further.
- SSEManager.setup() ran at import time (app.api.utils) via
get_event_loop(); this only worked because uvicorn imports the app
inside its loop and would break when imported without a running loop
(e.g. a Celery worker). Start the broadcast consumer lazily from
within a running loop instead.
- everywhere else the pattern was get_event_loop().create_task(x)
inside a coroutine; replace with asyncio.create_task(x).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
sign_jwt added JWT_EXPIRY_TIME (seconds) to a milliseconds epoch and
stored it in a custom 'expires' claim, while register_cookie_updater
slept JWT_EXPIRY_TIME as seconds. With the code default (300) tokens
effectively expired almost immediately; with the sampled 3600000 the
cookie-refresh loop slept ~41 days, so the local .cookie held an
expired token nearly always. The custom claim also meant PyJWT never
validated expiry itself.
- issue standard 'iat'/'exp' claims (seconds) and let PyJWT validate,
requiring 'exp' on decode
- derive the cookie refresh interval from the same unit, guarded
against tiny/negative values
- default BAPI_JWT_EXPIRY_TIME to 3600s and fix .env_sample (was
3600000 'milliseconds')
Existing tokens and the local .cookie are invalidated by this change;
clients re-login and the cookie regenerates at startup.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
If the environment variable BAPI_ENV_PATH is set, the config system will
try to read configs from the given path instead of .env in pwd
If no file is found .env in pwd will be used as a fallback
Env variables will always override settings in .env files.
This is only useful for application running directly on the Raspiblitz.
This will create a file in ~/.blitz_api/.cookie with a valid JWT token.
Local applications can use this to authenticate to the API without
having to ask for the password. This is similar to how Bitcoin Cores
cookie auth works.