P2-1 (containment): api/nestquest_core.py no longer mutates sys.path.
Load core by file location with importlib.util.spec_from_file_location,
registering it under the distinct top-level name 'nestquest_core' with
submodule_search_locations pointing at the bundled core directory. No
generic top-level names (db, const, schema, ...) are published that
could shadow a future dependency, and the integration's HA-coupled
__init__ is never executed. Use importlib.import_module for submodules;
drop the redundant _BOOTSTRAPPED flag. Document that two core copies
(nestquest_core.* and custom_components.nestquest.core.*) coexist in
the pytest process so later tasks must not compare class/exception
identity across them.
P2-2 (fail fast): ApiConfig.from_env now RAISES ConfigError when
NESTQUEST_DB_PATH is unset or empty — no silent fallback to a
predictable world-writable temp path that loses data at reboot. Remove
the module-level 'app = create_app()' (it read env at import time and
would break fail-fast); document serving with 'uvicorn --factory
api.app:create_app'.
P3 cleanups:
- /health drops db_path from the body (no filesystem path leak on an
unauthenticated route) and runs a cheap SELECT 1 to reflect database
reachability.
- Remove dead code: resolve_db_path in api/config.py; unused LOGGER in
api/app.py.
- tests/test_api_health.py: add ApiConfig.from_env tests (set value,
empty raises, missing raises); add startup-failure tests (unwritable
dir, non-SQLite file); assert shutdown closes the connection
(connected is False); make _AppRunner.__aexit__ use try/finally so a
client error still shuts down the lifespan; reuse api.database._executor
instead of a duplicated local copy; in the no-HA subprocess test
assert core.__file__ points at the bundled directory and stop passing
the unused ':memory:'.
- pyproject.toml: comment that fastapi/uvicorn are dev-group only so the
monorepo test venv can exercise the app; the API deployable's runtime
dependencies must be declared when it is packaged (Feature 17).
Add api/ with a FastAPI app that imports the bundled NestQuest core
(Feature 15) WITHOUT importing homeassistant: api/nestquest_core.py
bootstraps the integration directory onto sys.path and imports core as
a top-level package, so custom_components/nestquest/__init__.py (which
imports HA) never executes. This transitional coupling is encapsulated
in one documented helper to revisit in Feature 18.
The app reads NESTQUEST_DB_PATH (env var, documented temp default),
opens+migrates the SQLite database in a FastAPI lifespan, and serves
GET /health (200, status ok + resolved db_path) and the OpenAPI doc at
/docs and /openapi.json. Tests start the app with httpx against the
ASGI app and assert all three; a subprocess test proves the app
imports core without importing homeassistant or registering
custom_components.
Add fastapi, uvicorn, httpx to the dev dependency group; uv lock.
Suite green at 1581 (1576 baseline + 5 new API tests).