Parent: #14
Reproduced CI evidence
Diagnostic PR #18 / Actions job 94998930748 ran the PostgreSQL suite with -vv and faulthandler_timeout=30.
Observed sequence:
tests/test_admin_api_permissions.py::test_management_apis_require_admin_role passed.
- The next test,
test_webnovel_read_apis_require_login_not_admin, never reached its body.
- After 30s, faulthandler showed pytest blocked in async fixture setup (
pytest_asyncio async-generator fixture wrapper / event loop select).
- The suite remained blocked until the 180s diagnostic shell timeout killed it (exit 124).
- PostgreSQL logged an open transaction when the process was killed.
Root-cause chain
admin_api_client is a permission-test fixture backed by an in-memory SQLite DB, but the first test includes /settings/duckdb/status in its endpoint list.
For the admin request that endpoint calls the real module-level duckdb_service.get_analytics().status(). The singleton opens an in-memory DuckDB connection and ATTACHes the configured CI PostgreSQL database read-only. The permission fixture does not close/reset that global analytics singleton at teardown.
Before every test, the global autouse clean_tables fixture executes TRUNCATE TABLE ... CASCADE across the PostgreSQL schema. After the first permission test has opened the real DuckDB/Postgres attach, setup for the second test can wait on that database resource/transaction instead of reaching the test body.
The repository already has the correct isolation pattern in test_settings_notifications_api.py::test_duckdb_status_reports_database_diagnostics, which monkeypatches duckdb_service.get_analytics with FakeAnalytics.
Objective
Make the admin authorization test hermetic: it must validate authorization status codes without opening the real DuckDB analytical layer or PostgreSQL attachment.
Minimal fix
- monkeypatch
app.services.duckdb_service.get_analytics in admin_api_client to a deterministic fake analytics status;
- do not weaken the 401/403/200 assertions;
- do not change production DuckDB behavior;
- keep the dedicated DuckDB status behavior test as the place that validates endpoint payload/diagnostics.
Acceptance gates
- the two first tests in
test_admin_api_permissions.py run sequentially without fixture hang against PostgreSQL CI;
test_management_apis_require_admin_role still verifies /settings/duckdb/status is admin-only;
- permission tests do not initialize the module-level real DuckDB analytics singleton;
- diagnostic suite progresses beyond the second test;
- no production code changes are required unless new evidence proves otherwise;
- final PR contains durable test code only, no process artifacts.
Verifier focus
Verify this is isolation rather than hiding behavior: the dedicated DuckDB status test must continue to cover status payload behavior separately.
Parent: #14
Reproduced CI evidence
Diagnostic PR #18 / Actions job
94998930748ran the PostgreSQL suite with-vvandfaulthandler_timeout=30.Observed sequence:
tests/test_admin_api_permissions.py::test_management_apis_require_admin_rolepassed.test_webnovel_read_apis_require_login_not_admin, never reached its body.pytest_asyncioasync-generator fixture wrapper / event loop select).Root-cause chain
admin_api_clientis a permission-test fixture backed by an in-memory SQLite DB, but the first test includes/settings/duckdb/statusin its endpoint list.For the admin request that endpoint calls the real module-level
duckdb_service.get_analytics().status(). The singleton opens an in-memory DuckDB connection and ATTACHes the configured CI PostgreSQL database read-only. The permission fixture does not close/reset that global analytics singleton at teardown.Before every test, the global autouse
clean_tablesfixture executesTRUNCATE TABLE ... CASCADEacross the PostgreSQL schema. After the first permission test has opened the real DuckDB/Postgres attach, setup for the second test can wait on that database resource/transaction instead of reaching the test body.The repository already has the correct isolation pattern in
test_settings_notifications_api.py::test_duckdb_status_reports_database_diagnostics, which monkeypatchesduckdb_service.get_analyticswithFakeAnalytics.Objective
Make the admin authorization test hermetic: it must validate authorization status codes without opening the real DuckDB analytical layer or PostgreSQL attachment.
Minimal fix
app.services.duckdb_service.get_analyticsinadmin_api_clientto a deterministic fake analytics status;Acceptance gates
test_admin_api_permissions.pyrun sequentially without fixture hang against PostgreSQL CI;test_management_apis_require_admin_rolestill verifies/settings/duckdb/statusis admin-only;Verifier focus
Verify this is isolation rather than hiding behavior: the dedicated DuckDB status test must continue to cover status payload behavior separately.