fix: load .env into os.environ after environs 9 → 15 bump (#872)
environs 14.0.0 changed Env.read_env() to populate the Env instance's private _environ dict instead of mutating os.environ. PR #844 bumped environs 9.5.0 → 15.0.1 without catching this. Code paths reading typed values through env.str() / env.bool() kept working because Env._get_value() falls back to self._environ, but every os.environ.get() and os.getenv() callsite — including _load_jwt_secret() in app/auth/utils.py, which is invoked at class-body import time — silently stopped seeing .env values. The symptom: `uvicorn copilot:app` from backend/ now needs `--env-file ../.env` to boot. Previously the .env was loaded by the transitive import chain (copilot.py → app.auth.utils → app.auth.services.universal → app.db.db_session → env.read_env). That chain still runs, but no longer publishes anything to os.environ. Replace the two env.read_env(...) calls with python-dotenv's load_dotenv(...), which still mutates os.environ. Add a third load_dotenv at the very top of copilot.py (before any `from app...` import) so JWT_SECRET is available the instant AuthHandler's class body executes — independent of the import order downstream. Also fix a latent path bug in both db_session.py and data_store_session.py: Path(__file__).parent.parent / ".env" resolved to backend/app/.env, not the repo-root .env. environs' recurse=True walked up and found the real file by accident; with load_dotenv (no recurse) the path has to be correct, so this is now four parents up. Verified by force-recreating the backend container off the patched image: "Application startup complete" logs cleanly and POST /api/auth/token returns a real 401 from the DB-backed auth flow, confirming JWT_SECRET loaded at import time. Co-authored-by: taylor_socfortress <taylor.walton@socfortress.co> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>