к.м.н. по психиатрии, Институт Бехтерева, 2015Senior / Staff Architecture Showcase

О проекте RDD (Registry-Driven Development)

RDD — это специализированный веб-регистр для лонгитюдного ведения пациентов с рекуррентным депрессивным расстройством и одновременно полнофункциональное архитектурное портфолио уровня Senior / Staff Engineer. Система решает ключевую проблему медицинских исследований: сбор сложноструктурированных динамических клинических данных с защитой от потери информации и рассинхрона кодовой базы.

1. Клинический контекст и предыстория

В основе модели данных регистра лежит 6-летнее исследование рекуррентного депрессивного расстройства у пациентов позднего возраста, проведённое автором в Национальном медицинском исследовательском центре психиатрии и неврологии им. В.М. Бехтерева (Санкт-Петербург, 2015 г., степень кандидата медицинских наук).

Какую клиническую проблему решает проект?

В психиатрических исследованиях традиционные инструменты (электронные таблицы Excel, универсальные опросники Google Forms, системы типа RedCap) быстро заходят в тупик: они не умеют валидировать временную последовательность аффективных фаз, не связывают смену фармакотерапии с динамикой симптомов и допускают противоречивые данные. RDD переносит врачебную логику непосредственно в архитектуру системы: нормализованный паспорт пациента, динамическая матрица фаз (1..N, поступление, выписка), включающая данные о клинической картине фаз и интермиссий, эффективности лечения, психометрические шкалы.

2. Архитектура: Registry-Driven Core (SSOT)

Главная проблема медицинских систем с десятками клинических признаков — сложность адаптации приложения к изменениям дизайна исследования. При внедрении изменений есть постоянный риск рассинхронизации между схемой базы данных, валидацией на бэкенде, UI-компонентами форм и словарём данных. В RDD реализован подход Single Source of Truth:

01. Описание

Единый декларативный TypeScript-объект (src/shared/config/registry/) описывает каждое поле: тип данных SQLite, UI-компонент, диапазон допустимых значений (min/max), клинические варианты выбора и формулы вычисления.

02. Генерация

Из этого реестра генератор gen:d1 автоматически формирует D1-миграции, валидаторы Zod строятся на лету (to-zod.ts), интерфейс карточек рендерится декларативно, а Data Dictionary обновляется без участия разработчика.

03. Инвариант

Инвариант «Поле = Колонка»: бинарные признаки хранятся как плоские INTEGER 0/1. Это позволило отказаться от непрозрачных JSON-полей и тяжелых EAV-паттернов, обеспечив прямые высокоскоростные SQL-агрегаты.

3. Высокопроизводительная матрица фаз (Matrix Grid)

Часто в подобных приложениях возникают проблемы с удобством заполнения клинических признаков, интерфейс может подтормаживать из-за большого количества данных. Мы разработали "Матрицу фаз" — центральный инструмент врача, одновременно отображающий сотни ячеек признаков заболевания:

Гибридный скролл без JS

Гибридный скролл без JS-синхронизации: строки рендерятся через CSS Grid, где левая колонка наименования признака имеет нативное правило "position: sticky". Это исключило рассинхронизацию независимых слоев прокрутки.

Виртуализация TanStack

Виртуализация TanStack Virtual: рендерятся исключительно строки, попадающие в видимый viewport экрана, что гарантирует мгновенный отклик даже на больших клинических картах.

Атомарный Zustand-стор

Атомарное состояние на Zustand: изменение ячейки обновляет только конкретный DOM-узел через селекторы подписки, исключая перерисовку всей таблицы.

CAS-контроль версий (409)

Защита от потери данных (Compare-And-Swap): одновременные правки нескольких врачей проверяются по версии записи. В случае конфликта (HTTP 409 Conflict) врач видит разницу своего значения и версию коллеги — тихая перезапись исключена на уровне архитектуры.

4. Edge-инфраструктура, аудит и безопасность

Приложение развернуто в бессерверном рантайме Cloudflare (Workers + Pages + D1 Database) на базе Next.js 16 App Router с нулевым cold start:

Шифрование (Web Crypto)

Криптография на Web Crypto API: из-за отсутствия node:crypto на Edge хэширование паролей реализовано через PBKDF2-SHA256 (100 000 итераций) с солью. Токен сессии хранится в HttpOnly; Secure; SameSite=Lax cookie, а в БД — только SHA-256 дайджест.

Разграничение доступа к картам

Разграничение доступа к данным: каждому пользователю назначен объём видимости (data_scope) — «все» (all), «свой центр» (site) или «назначенные пациенты» (assigned). Репозиторий сам добавляет фильтр в каждый запрос, поэтому по прямой ссылке нельзя открыть чужую карту (IDOR).

Журнал изменений

Журнал изменений, который нельзя переписать: каждое изменение пишется в audit_log одной транзакцией с данными, а записи связаны хэшами (prev_hash/entry_hash) — подменить историю незаметно нельзя.

5. Границы демонстрационного проекта и продакшен

Проект создан для демонстрации инженерных подходов системного проектирования и доменной экспертизы. В спеках явно разграничены текущий функционал и требования боевого контура:

Текущий демо-контур

Текущий контур: полностью функциональная бизнес-логика регистра с синтетическими медицинскими профилями на серверах Cloudflare.

Требования для продакшена

Продакшен-эскалация: для эксплуатации с реальными пациентами требуется сертификация (152-ФЗ / HIPAA), Cloudflare WAF, Point-in-Time Recovery бэкапы D1 и интеграция с внешними МИС/ЕГИСЗ через HL7 FHIR.