You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Сравнение файлов smart-on-fhir.md (оригинал, основан на спецификации) и smart-on-fhir-detailed.md (обзорный, основан на знаниях модели).
Общая характеристика
smart-on-fhir.md (оригинал)
smart-on-fhir-detailed.md (обзорный)
Объём
~450 строк
~380 строк
Разделов
14
15
Источник
Спецификация (FHIR KG)
Знания модели
Фокус
Спецификация изнутри
Спецификация снаружи (с контекстом экосистемы и индустрии)
Есть в оригинале, нет в обзорном
Тема
Что именно
Capability Sets
Конкретные наборы capabilities для 4 типовых сценариев: Patient Access Standalone, Patient Access EHR Launch, Clinician Standalone, Clinician EHR Launch — с перечислением обязательных capabilities для каждого
User Access Brands
Целый раздел о том, как организации публикуют свои «визитки» (Brand → Portal → Endpoint), чтобы пациент мог найти своего провайдера в приложении. Иерархия: один бренд → несколько порталов → несколько FHIR-эндпоинтов
Task Launch
Профили FHIR Task (task-ehr-launch, task-standalone-launch) для программного запроса запуска SMART-приложения с appContext
App State
Экспериментальная возможность хранить настройки приложения в EHR через Basic-ресурс: лимит 256KB, обязательный If-Match/ETag, запрет на клинические данные
Best Practices
Конкретные рекомендации: напоминать об offline-доступе, отзывать токен при повторном использовании refresh token, DPoP/UDAP, описывать scopes простым языком
Список EHR (Epic, Cerner, Allscripts, MEDITECH), open-source серверов (HAPI, Microsoft, IBM, Google), песочниц (launch.smarthealthit.org, Logica, Epic Sandbox)
Ограничения и критика
5 конкретных проблем: сложность OAuth в медконтексте, неконсистентность реализаций, производительность REST/JSON, широкие scopes, трудность тестирования без EHR
История
Josh Mandel, Ken Mandl, 2010 год, Boston Children's Hospital, финансирование ONC
Token Revocation
Отдельно описан POST /auth/revoke (в оригинале есть только introspection)
Описано в обоих, но по-разному
Тема
Оригинал
Обзорный
Discovery
Более полный JSON-пример (включает introspection_endpoint, capabilities список)
Более полный JSON (включает scopes_supported, code_challenge_methods_supported)
Scopes
Подробнее: принцип делегирования прав («скоупы не расширяют права пользователя»), конкретные примеры в таблице
Подробнее: granular scopes с query-параметрами (?category=vital-signs)
Типы клиентов
Подробнее: конкретный JWT header/payload для asymmetric auth, обязательные алгоритмы RS384/ES384
Короче, но яснее структурирован
Backend Services
Подробнее: 4 конкретных use case, отличия от App Launch списком, нет refresh tokens
Короче, но с полным code example
Introspection
Подробнее: полный JSON-ответ с client_id, fhirUser, контекст launch
Короче: минимальный JSON
Итоговая диаграмма
ASCII-дерево всей архитектуры (App Launch / Backend / вспомогательные)
Простая трёхуровневая диаграмма App → Auth+FHIR → EHR
Фактические расхождения
Прямых противоречий нет — оба описания корректны. Разница в глубине и фокусе.
Вердикт
Оригинал лучше как техническое справочное описание. Он точнее, полнее покрывает спецификацию (Brands, App State, Task Launch, Capability Sets), и основан на первоисточнике.
Обзорный лучше как вводный материал. Он даёт больше контекста (регуляторика, история, экосистема), более доступен для читателя, не знакомого с FHIR, и включает практическую информацию (где попробовать, какие EHR поддерживают).
Идеальный вариант — объединить: взять структуру и техническую точность оригинала, добавить из обзорного регуляторный контекст, сравнение v1/v2, CDS Hooks, практические реализации и критику.
До появления SMART on FHIR интеграция с медицинскими системами выглядела так:
Каждый EHR-вендор (Epic, Cerner, Allscripts, MEDITECH) имел собственный проприетарный API
Разработчику приложения нужно было писать отдельную интеграцию под каждую систему
Авторизация реализовывалась кастомно — от VPN-туннелей до хардкод-паролей
Смена EHR-системы в клинике означала потерю всех сторонних приложений
Идея SMART (Substitutable Medical Applications, Reusable Technologies) родилась в 2010 году в Harvard Medical School / Boston Children's Hospital под руководством Josh Mandel и Ken Mandl. Первоначально проект финансировался ONC (Office of the National Coordinator for Health IT).
Цель: создать "app store" для медицины — экосистему, где приложения подключаются к любой EHR так же просто, как веб-приложения авторизуются через Google/Facebook.
Альтернативно, эта информация доступна через FHIR CapabilityStatement (расширение security).
4. Сценарии запуска (Launch)
4.1 EHR Launch
Приложение запускается изнутри EHR. Типичный сценарий: врач работает с картой пациента и кликает на кнопку/иконку приложения.
Шаг 1: EHR открывает URL приложения с параметрами:
https://app.example.com/launch?iss=https://ehr.example.com/fhir&launch=abc123
Шаг 2: Приложение извлекает iss (адрес FHIR-сервера) и launch (одноразовый токен)
Шаг 3: Приложение обращается к .well-known/smart-configuration
чтобы узнать authorization_endpoint
Шаг 4: Приложение перенаправляет пользователя на авторизацию:
GET /auth/authorize?
response_type=code&
client_id=my-app&
redirect_uri=https://app.example.com/callback&
scope=launch patient/Observation.rs openid fhirUser&
launch=abc123&
state=xyz789&
code_challenge=...&
code_challenge_method=S256
Шаг 5: Authorization Server проверяет launch-токен,
определяет контекст (пациент, encounter),
спрашивает согласие если нужно
Шаг 6: Редирект обратно в приложение с authorization code:
https://app.example.com/callback?code=AUTH_CODE&state=xyz789
Шаг 7: Приложение обменивает code на access token:
POST /auth/token
grant_type=authorization_code&
code=AUTH_CODE&
redirect_uri=...&
code_verifier=...
Шаг 8: Ответ с токеном и контекстом:
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "launch patient/Observation.rs openid fhirUser",
"patient": "Patient/123",
"encounter": "Encounter/456",
"id_token": "eyJ..."
}
Ключевой момент: поле patient в ответе токена — это контекст, переданный из EHR. Приложению не нужно спрашивать "какой пациент?" — EHR уже сообщил это.
4.2 Standalone Launch
Приложение запускается самостоятельно, вне контекста EHR. Типичный сценарий: пациент открывает мобильное приложение для просмотра своих медицинских данных.
Отличия от EHR Launch:
Нет параметра launch — приложение само знает iss
Приложение запрашивает scope launch/patient чтобы получить picker выбора пациента
Пользователь сам выбирает пациента (или Authorization Server определяет его автоматически, если это пациент-портал)
Scopes определяют, что именно приложение может делать с данными. SMART v2 использует формат:
<context>/<resourceType>.<interactions>
Контексты
Контекст
Значение
patient
Доступ ограничен данными конкретного пациента из контекста
user
Доступ определяется правами текущего пользователя (врач может видеть многих пациентов)
system
Backend-to-backend доступ без пользователя
Interactions (SMART v2)
Код
Операция
c
create
r
read
u
update
d
delete
s
search
Примеры:
patient/Observation.rs — читать и искать наблюдения текущего пациента
user/Patient.cruds — полный доступ к пациентам в рамках прав пользователя
patient/MedicationRequest.r — только чтение назначений текущего пациента
system/*.rs — backend-сервис читает и ищет все ресурсы
Специальные scopes
Scope
Назначение
openid
Получить id_token (идентификация пользователя через OpenID Connect)
fhirUser
Получить ссылку на FHIR-ресурс пользователя (Practitioner/123 или Patient/456)
launch
Принять EHR launch контекст
launch/patient
Запросить выбор пациента при standalone launch
launch/encounter
Запросить контекст encounter
offline_access
Получить refresh token для длительного доступа
Granular Scopes (SMART v2)
SMART v2 добавил возможность фильтрации внутри scope:
Revocation — приложение может отозвать токен (при logout):
POST /auth/revoke
token=eyJ...
10. SMART App Launch v1 vs v2
Аспект
v1
v2
Scopes
patient/Observation.read
patient/Observation.rs (гранулярные)
PKCE
Рекомендуется
Обязателен для public clients
Асимметричная auth
Не стандартизирована
Полностью описана
Granular scopes
Нет
Фильтрация по category, code и др.
Token introspection
Не описана
Стандартизирована
FHIR версия
DSTU2, STU3, R4
R4+
Статус
Устарел
Текущий стандарт (STU 2.0)
11. Регуляторный контекст (США)
SMART on FHIR стал юридически значимым:
21st Century Cures Act (2016) — закон, запрещающий information blocking
ONC Final Rule (2020) — требует от сертифицированных EHR поддержку FHIR R4 API с авторизацией SMART on FHIR
CMS Interoperability Rules — страховые компании (payers) обязаны предоставлять Patient Access API на основе FHIR + SMART
Практически: начиная с 2022-2023 года все крупные EHR в США (Epic, Cerner/Oracle Health, Allscripts, MEDITECH) обязаны поддерживать SMART on FHIR.
12. CDS Hooks — расширение экосистемы
CDS Hooks (Clinical Decision Support Hooks) — связанный стандарт, который использует SMART on FHIR для авторизации:
1. Врач открывает назначение лекарства в EHR
2. EHR отправляет webhook на CDS-сервис:
POST https://cds.example.com/cds-services/drug-interactions
{
"hook": "medication-prescribe",
"fhirServer": "https://ehr.example.com/fhir",
"fhirAuthorization": { "access_token": "eyJ..." },
"context": { "patientId": "123", "medications": [...] }
}
3. CDS-сервис анализирует, возвращает "cards":
{
"cards": [{
"summary": "Взаимодействие: Варфарин + Ибупрофен",
"indicator": "critical",
"detail": "Повышенный риск кровотечения...",
"suggestions": [{ "label": "Заменить на Парацетамол" }]
}]
}
4. EHR показывает предупреждение врачу
13. Практические реализации
Крупнейшие EHR с поддержкой SMART:
Epic — App Orchard / Open Epic, крупнейшая экосистема SMART-приложений
Cerner (Oracle Health) — Code Console, полная поддержка v1 и v2
Allscripts — Open API
MEDITECH — Greenfield platform
Open-source FHIR-серверы с поддержкой SMART:
HAPI FHIR (Java) — с модулем авторизации
Microsoft FHIR Server (C#) — Azure Health Data Services
IBM FHIR Server (Java, сейчас LinuxForHealth)
Google Cloud Healthcare API — managed FHIR с SMART
Тестовые песочницы:
SMART Health IT Sandbox (launch.smarthealthit.org) — для разработки и тестирования
Logica Health (ранее HSPC) — открытые песочницы
Epic FHIR Sandbox — тестовые данные Epic
14. SMART Health Cards (бонус)
Отдельная, но связанная инициатива — SMART Health Cards (использовались для COVID-сертификатов):
Verifiable Credential в формате JWT, сжатый и упакованный в QR-код
Содержит FHIR Bundle (Patient + Immunization)
Подписан ключом организации (проверяемый через JWKS)
Не требует онлайн-подключения для верификации
Это не SMART on FHIR в классическом смысле, но разделяет философию: FHIR как формат данных + криптография для доверия.
15. Ограничения и критика
Сложность внедрения — OAuth 2.0 в медицинском контексте нетривиален, много edge cases
Неконсистентность реализаций — каждый EHR реализует стандарт с нюансами (особенно scopes и launch)
Производительность — REST/JSON не оптимален для bulk-операций (решается через FHIR Bulk Data Access)
Безопасность — токены с широкими scopes (patient/*.cruds) дают слишком много доступа; granular scopes v2 решают это частично
Тестирование — сложно тестировать launch flow без реального EHR
Резюме
SMART on FHIR = OAuth 2.0 (авторизация) + FHIR (данные) + Launch Framework (контекст). Это превратило медицинские системы из закрытых монолитов в платформы с экосистемой приложений, аналогично тому, как App Store изменил мобильные телефоны. Стандарт стал регуляторным требованием в США и де-факто международным подходом к интеграции клинических приложений.
SMART (Substitutable Medical Applications, Reusable Technologies) on FHIR — это спецификация, которая решает одну фундаментальную проблему: как стороннее приложение может безопасно получить доступ к медицинским данным в EHR-системе?
До SMART каждая EHR-система имела свой проприетарный способ интеграции приложений. Врач или пациент, желающий использовать стороннее приложение (визуализация данных, поддержка принятия решений, мобильный портал), был привязан к экосистеме конкретного вендора. SMART создаёт единый стандарт, позволяющий написать приложение один раз и запускать его на любой совместимой EHR-системе — по аналогии с тем, как веб-приложения работают в любом браузере.
Технически SMART — это профиль поверх OAuth 2.0, адаптированный для здравоохранения. Он не изобретает авторизацию с нуля, а берёт промышленный стандарт и добавляет к нему то, что нужно в медицинском контексте: передачу контекста пациента, гранулярные права на FHIR-ресурсы, стандартизированный запуск приложений.
Четыре сценария использования
SMART App Launch Framework поддерживает четыре ключевых сценария:
Приложение пациента, запускаемое самостоятельно — пациент открывает мобильное приложение на своём телефоне
Приложение пациента, запускаемое из портала — пациент кликает на приложение внутри Patient Portal
Приложение врача, запускаемое самостоятельно — врач открывает аналитическое приложение на своём компьютере
Приложение врача, запускаемое из EHR — врач кликает на приложение внутри интерфейса электронной карты
Эти сценарии покрывают визуализацию данных, сбор данных, клиническую поддержку решений (CDS), обмен данными, эпидемиологическую отчётность и многое другое.
Два режима запуска
EHR Launch
В режиме EHR Launch пользователь уже работает в EHR-системе и решает запустить приложение. EHR открывает новое окно браузера (или iframe), указывающее на зарегистрированный URL приложения, и передаёт два параметра:
Приложение потом включает этот launch-токен в запрос авторизации, и сервер возвращает контекст (ID пациента, encounter и т.д.) вместе с access token.
Standalone Launch
В режиме Standalone Launch приложение запускается извне — пациент открывает мобильное приложение или врач переходит по закладке. Контекст не передаётся заранее; вместо этого приложение запрашивает у сервера установить контекст в процессе авторизации. Например, scope launch/patient просит сервер предложить пользователю выбрать пациента.
Пошаговый flow авторизации
Полный процесс SMART App Launch состоит из семи шагов:
Шаг 1. Регистрация приложения (однократно, вне полосы)
Приложение регистрируется в авторизационном сервере EHR: фиксирует launch URL, redirect URI, тип клиента. Для confidential-клиентов устанавливается секрет или набор ключей (JWKS).
Шаг 2. Запуск
EHR Launch (с iss + launch) или Standalone Launch (приложение запускается само).
Шаг 3. Discovery
Приложение запрашивает GET {fhir-base}/.well-known/smart-configuration и получает JSON с ключевыми URL:
Сервер показывает пользователю экран согласия и, при одобрении, редиректит обратно с code.
Шаг 5. Обмен code на access token
Приложение делает POST на token_endpoint:
POST /auth/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=abc123&
redirect_uri=https://app/callback&
code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Для confidential-клиентов добавляется аутентификация (Basic Auth с client_secret или JWT assertion).
Шаг 6. Доступ к FHIR API
С полученным access token приложение обращается к ресурсам:
GET /fhir/Patient/123
Authorization: Bearer eyJ0eXAi...
Шаг 7. Обновление токена
Если приложение запросило offline_access или online_access, оно получает refresh token и может обновлять access token без повторного входа пользователя.
Система скоупов (Scopes)
SMART Scopes — это сердце системы прав доступа. Скоупы делятся на три категории:
patient/ — доступ в контексте конкретного пациента
user/ — доступ в контексте текущего пользователя (с учётом его привилегий)
system/ — системный доступ (для backend-сервисов)
Операции (CRUDS):
c — create
r — read, vread, history (instance)
u — update, patch
d — delete
s — search, history (type/system level)
Примеры:
Скоуп
Что даёт
patient/Observation.rs
Чтение и поиск Observation для текущего пациента
user/Patient.cruds
Полный доступ к Patient-ресурсам в рамках привилегий пользователя
patient/Observation.rs?category=laboratory
Только лабораторные наблюдения (гранулярный v2)
system/Patient.rs
Системное чтение всех пациентов (для backend-сервисов)
Для обратной совместимости с v1: .read → .rs, .write → .cud, .* → .cruds.
2. Скоупы для контекста запуска
launch — получить контекст при EHR Launch
launch/patient — попросить сервер установить контекст пациента
launch/encounter — попросить установить контекст encounter
3. Скоупы для identity
openid fhirUser — получить информацию о текущем залогиненном пользователе
offline_access — refresh token, работающий после выхода пользователя
online_access — refresh token, работающий пока пользователь онлайн
Важный принцип: скоупы делегируют права, но не расширяют их. Если у пользователя нет доступа к определённым данным, скоуп user/*.cruds не даст приложению больше прав, чем имеет сам пользователь.
Типы клиентов и аутентификация
Public app
Приложения, которые не могут хранить секрет: браузерные SPA, мобильные приложения. Секрет, встроенный в код, может быть извлечён пользователем. Такие приложения:
Не передают client_secret
Обязательно используют PKCE для защиты authorization code
Пример: HTML5/JS приложение, iOS-приложение
Confidential app — symmetric
Серверные приложения с shared secret. Аутентификация — HTTP Basic Auth:
Подходит для App Launch, но не рекомендуется для Backend Services.
Confidential app — asymmetric
Предпочтительный способ для серьёзных интеграций. Клиент регистрирует свой публичный ключ (через JWKS URL или напрямую) и аутентифицируется подписанным JWT:
Клиент подписывает JWT своим приватным ключом и передаёт в client_assertion. Сервер верифицирует подпись по зарегистрированному публичному ключу. Обязательная поддержка алгоритмов: RS384 и ES384.
Backend Services
SMART Backend Services — отдельный профиль для серверных (machine-to-machine) интеграций без участия пользователя. Примеры:
Аналитическая платформа, периодически импортирующая bulk data из EHR
Лабораторный мониторинг, проверяющий результаты и генерирующий алерты
Интеграционный сервис, синхронизирующий новых пациентов с внешней базой
Система мониторинга загруженности палат, обновляющая данные каждую минуту
Отличия от App Launch:
Нет пользовательской авторизации — клиент предварительно авторизован сервером
Используется client_credentials grant (не authorization_code)
Только asymmetric аутентификация (подписанный JWT)
Скоупы обычно system/ (например, system/Observation.rs)
Токены короткоживущие (рекомендуется 5 минут), refresh tokens не выдаются
Процесс:
Регистрация клиента + передача публичного ключа
Discovery (/.well-known/smart-configuration)
POST на token endpoint с JWT assertion → получение access token
Использование access token для доступа к FHIR API
Token Introspection
Token Introspection (RFC 7662) позволяет resource-серверам проверять валидность токенов. Это важно в архитектурах, где авторизационный сервер и ресурсный сервер разделены.
Ответ introspection включает:
active — жив ли токен
scope — выданные права
client_id — кому выдан
exp — время истечения
launch context (patient, intent) — если был передан при выдаче
Сервер объявляет свои возможности через SMART Configuration в /.well-known/smart-configuration. Capabilities группируются в Capability Sets для типовых сценариев:
Отдельные capabilities включают: режимы запуска (launch-ehr, launch-standalone), типы клиентов (client-public, client-confidential-symmetric, client-confidential-asymmetric), контексты, разрешения (permission-v1, permission-v2, permission-offline), SSO (sso-openid-connect).
User Access Brands
Одна из новейших частей спецификации — Brands. Она решает проблему UX: когда пациент открывает приложение и хочет подключиться к своему провайдеру, он должен найти его в списке. Brands стандартизирует, как организации публикуют свою «визитку»:
Brand (Organization) — название, логотип, адреса, категории (клиника, лаборатория, страховая)
Portal — пользовательский портал с названием, URL, описанием
Endpoint — FHIR API endpoint, привязанный к порталу
Иерархия гибкая: один бренд может иметь несколько порталов, один портал — несколько FHIR-эндпоинтов (R2 и R4), несколько брендов могут вести к одному порталу (региональная сеть клиник).
Brands публикуются в виде FHIR Bundle и указываются в user_access_brand_bundle в SMART configuration.
Task Launch
Для интеграции с CDS (Clinical Decision Support) определены профили FHIR Task, которые запрашивают запуск SMART-приложения:
task-ehr-launch — запрос на EHR Launch с опциональным appContext (аналогично CDS Hooks Link)
task-standalone-launch — запрос на Standalone Launch
Это позволяет, например, CDS-движку создать Task «запустите приложение калькулятора дозировки билирубина» с контекстом пациента и encounter.
App State (экспериментальная возможность)
SMART App State позволяет приложениям сохранять небольшой объём конфигурации в EHR через FHIR API (Basic ресурс):
Пользовательские настройки — экран по умолчанию, цветовая тема, shortcuts
Ключи шифрования — для доступа к внешним зашифрованным данным
Ограничения:
Нельзя хранить клинические данные (для них есть FHIR-ресурсы)
EHR не обязана интерпретировать хранимые данные
Максимум 256KB на ресурс
Обязательное управление конкурентностью через If-Match / ETag
Контроль доступа — через SMART scopes: user/Basic.cuds (для пользовательских настроек), patient/Basic.cuds (для данных пациента), с возможностью гранулярного ограничения по state code.
Best Practices
Спецификация выделяет рекомендации для обеих сторон:
Для серверов:
Напоминать пользователям, какие приложения имеют offline-доступ
Отзывать авторизацию при повторном использовании refresh token (защита от кражи)
Рассматривать привязку refresh token к аппаратным ключам (DPoP, UDAP)
Для приложений:
Никогда не использовать refresh token повторно
При пользовательском присутствии — защищать секреты биометрией
Публично документировать политику обращения с данными
Для UX согласия:
Описывать скоупы простым языком, не медицинским жаргоном
Не пугать пациента словом «Encounters» — объяснять понятно
Публиковать скриншоты экранов согласия для разработчиков
SMART on FHIR — это не просто протокол авторизации. Это целая платформенная модель, позволяющая создать экосистему медицинских приложений: от простого просмотрщика лабораторных результатов на телефоне пациента до enterprise-интеграции, ежеминутно синхронизирующей данные между системами. Спецификация покрывает весь жизненный цикл: discovery, авторизация, доступ к данным, обновление токенов, обнаружение провайдеров, хранение состояния приложений.
Составлено на основе FHIR Knowledge Graph (2939 концептов, 5785 связей, 408 страниц спецификации) — 20 страниц SMART App Launch IG.