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).
Iterates present children from the Feature 10 presence sensors, lists
what each owes today from the remaining sensor, omits absent children
entirely. Blueprint inputs (time, notify service, send toggle); the
notify target is the household's choice, never hard-coded. PyYAML and
Jinja2 join the dev-only dependencies for blueprint template tests.