feat(backend): модель данных identity / clinical / audit, репозитории, create_all #29

Merged
Eleboba merged 1 commits from feat/6-db into dev 2026-10-03 14:59:53 +03:00
Owner

Что меняется

Модель данных: две раздельные БД (identity / clinical + audit_log) на SQLAlchemy 2.0 async, тонкие репозитории, init_db() (create_all) на старте приложения. Guardrail #5 проверяется тестами.

Closes #6

Зона

backend

Как проверить

  • make lint test (tests/test_db.py — sqlite in-memory, две БД)
  • На compose-Postgres: TEST_PG_IDENTITY_URL=postgresql+asyncpg://identity_app:identity_app@127.0.0.1:5432/identity TEST_PG_CLINICAL_URL=postgresql+asyncpg://clinical_app:clinical_app@127.0.0.1:5432/clinical uv run pytest tests/test_db.py
  • make up → в логе app db schema ready

Публичный API

  • app.db.session: get_identity_session(), get_clinical_session() (commit/rollback), configure(identity_url=, clinical_url=), dispose()
  • app.db.bootstrap.init_db()
  • app.db.repo: upsert_profile, get_profile, patients_of_doctor, upsert_checkin, list_checkins, add_item_response, add_scale_result, list_scale_results, add_alert, open_alert_codes, list_alerts, ack_alert, get_dialog_state, set_dialog_state, add_message, load_clock_offset, save_clock_offset
  • app.db.audit.audit(...), app.db.identity_repo.*

Чек-лист

  • rebase на origin/dev
  • make lint + make test зелёные
  • лог в issue (### 2026-10-03)
  • нет ПДн в логах, нет реальных данных, нет секретов
  • общие файлы не тронуты (кроме хука в app/main.py lifespan)
## Что меняется Модель данных: две раздельные БД (identity / clinical + audit_log) на SQLAlchemy 2.0 async, тонкие репозитории, `init_db()` (create_all) на старте приложения. Guardrail #5 проверяется тестами. Closes #6 ## Зона backend ## Как проверить - `make lint test` (`tests/test_db.py` — sqlite in-memory, две БД) - На compose-Postgres: `TEST_PG_IDENTITY_URL=postgresql+asyncpg://identity_app:identity_app@127.0.0.1:5432/identity TEST_PG_CLINICAL_URL=postgresql+asyncpg://clinical_app:clinical_app@127.0.0.1:5432/clinical uv run pytest tests/test_db.py` - `make up` → в логе app `db schema ready` ## Публичный API - `app.db.session`: `get_identity_session()`, `get_clinical_session()` (commit/rollback), `configure(identity_url=, clinical_url=)`, `dispose()` - `app.db.bootstrap.init_db()` - `app.db.repo`: `upsert_profile`, `get_profile`, `patients_of_doctor`, `upsert_checkin`, `list_checkins`, `add_item_response`, `add_scale_result`, `list_scale_results`, `add_alert`, `open_alert_codes`, `list_alerts`, `ack_alert`, `get_dialog_state`, `set_dialog_state`, `add_message`, `load_clock_offset`, `save_clock_offset` - `app.db.audit.audit(...)`, `app.db.identity_repo.*` ## Чек-лист - [x] rebase на origin/dev - [x] make lint + make test зелёные - [x] лог в issue (### 2026-10-03) - [x] нет ПДн в логах, нет реальных данных, нет секретов - [x] общие файлы не тронуты (кроме хука в `app/main.py` lifespan)
Eleboba added 1 commit 2026-10-03 14:58:59 +03:00
Two DeclarativeBases on two engines (ADR-003): identity holds direct
identifiers, clinical holds token-keyed pseudonymised data plus audit_log.
Portable types (JSONB variant, tz-aware UTC timestamps rejecting naive
values) so tests run on SQLite. init_db() runs create_all at startup.
Guardrail #5 checked by AST and import-graph tests.

Refs #6

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Eleboba merged commit 84317bcfce into dev 2026-10-03 14:59:53 +03:00
Eleboba deleted branch feat/6-db 2026-10-03 14:59:53 +03:00
Sign in to join this conversation.