1.x changed session-scoped async fixture/event-loop behavior across test
modules, breaking the single-shared-engine assumption tests/conftest.py's
engine fixture and the asyncio_default_*_loop_scope settings depend on.
Surfaced as sporadic "relation ... does not exist" failures in specific
integration test files when run alongside the full suite, despite those
same files passing cleanly when run standalone -- confirmed via a real
Postgres run on production hardware while verifying the watch-provider
dedup fix.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
The first authenticated-user concept in Aurora Core -- everything else in
this codebase is public, read-only catalog data. Foundation for ratings
and a watchlist (not yet built): POST /auth/register, POST /auth/login,
GET /auth/me.
Security specifics worth knowing:
- Passwords hashed with argon2 (via argon2-cffi), never stored plain or
logged.
- Login returns an identical 401 for a nonexistent email and a wrong
password on a real one, including matching response timing
(burn_time_like_a_password_check) -- otherwise either the status code
or the timing alone lets a client enumerate registered emails.
- AURORA_SECRET_KEY now actually signs JWTs (previously defined but
unused anywhere) -- .env.example's existing token_urlsafe(48) guidance
already produces a long enough key, just flagged its new stakes.
- Email matched case-insensitively via explicit normalization in the
service layer, not relied on from Pydantic's EmailStr (which does not
lowercase the local part).
12 new integration tests (register/login/me over real HTTP via the
`client` fixture) plus 10 unit tests for the hashing/JWT logic itself,
following the same-day lesson that only unit tests actually execute
locally without Postgres -- the auth core is tested for real here rather
than only through integration tests that might not run before a deploy.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Builds docs/ into a static site via mkdocs + mkdocs-material in its own
Docker build stage (docs-builder), so mkdocs itself never ends up in the
runtime image -- only the rendered HTML does, mounted at /wiki alongside
the existing /docs OpenAPI schema (unconditionally, unlike /docs, since
this is curated content meant to be public regardless of
AURORA_API_DOCS_ENABLED).
docs/aurora-core-spec.md (the internal build spec, referenced by "section
N" comments throughout the codebase) is excluded from the built site
entirely via exclude_docs, not just left out of the nav -- it was never
meant for public consumption.
Co-Authored-By: Claude Sonnet 5 <[email protected]>
tests/conftest.py's `engine` fixture is session-scoped (one asyncpg
engine/schema for the whole run, for speed), but pytest-asyncio's
default is a fresh event loop per test function. asyncpg connections
are bound to the event loop that created them, so every test after the
first failed with "cannot perform operation: another operation is in
progress" or "attached to a different loop" the moment it touched the
database. Pinning both the fixture and test loop scope to "session"
in pyproject.toml keeps everything on one loop, matching the
session-scoped engine.
Found by actually running the integration suite for the first time,
against real PostgreSQL + Redis on a devbox.
Co-Authored-By: Claude Sonnet 5 <[email protected]>