FHIR — основы и базовая notation описаны в fhir-basics. Эта страница — про эволюцию стандарта через major releases: DSTU2 (2015) → STU3 (2017) → R4 (2019) → R5 (2023) → R6 (в активном ballot, expected final late 2026 или вероятнее mid-late 20271). Каждый release ломает совместимость в отдельных ресурсах: переименовывают поля, удаляют backbone-элементы, добавляют новые reference targets.
Ballot — HL7-процесс formal voting на draft изменения. Спец проходит через несколько ballot cycles (ballot1, ballot2, …, каждый — раунд голосования + комментарии + refinement’ы), прежде чем становится final. R4 прошёл 3 ballots за ~18 месяцев. Между ballot’ами текст может изменяться — поэтому ссылаться на ballot версии как на final spec нельзя.
Релевантны сегодня R4 и R5: R4 — самый широко имплементированный (большинство EHR, US Core, IPS), R5 — currently published, но adoption ограниченный. R6 ещё не публикован — в ballot4 (hl7.fhir.core#6.0.0-ballot4, build от 14 мая 20262).
Главный design-trend R4 → R5: меньше inline, больше references
R5 систематически разбирает крупные backbone-элементы и заменяет их ссылками на специализированные ресурсы. Логика спецификации: один способ описать действие/событие/связь, не два.
Конкретные примеры из R5 changelog
- CarePlan.activity.detail удалён → заменён на
activity.plannedActivityReference(ссылка наServiceRequest,Task,RequestOrchestration,MedicationRequest,ImmunizationRecommendation,SupplyRequest). Inline-поляcode,priority,description,status,kindбольше не существуют — переезжают в referenced ресурс. См. fhir-careplan раздел “FHIR R5 implications” и fhir-service-request. - CarePlan.outcomeCodeableConcept / outcomeReference удалены → консолидированы в новое поле
performedActivity(CodeableReference). - Device.patient удалён → отдельный ресурс
DeviceAssociationдля контекста использования. Master-data Device отделён от его привязки к пациенту. См. fhir-device. - Encounter.hospitalization → переименован в
admission,statusHistory/classHistoryудалены, статус ушёл в новыйEncounterHistoryресурс. - Condition.recorder / asserter удалены → объединены в
participant.actor(универсальный паттерн). - AllergyIntolerance.recorder / asserter → тот же
participant.actorрефактор. - AdverseEvent — несколько inline полей (
date,severity,contributor) удалены, ушли вparticipantи supporting structures.
Источник3.
Что это за паттерн
Да, это прямая аналогия с database normalization: вместо денормализованной таблицы со всеми атрибутами в одной row выделяются типизированные сущности с foreign-key references. Trade-off зеркальный — больше join’ов / multiple writes на запись, более compact и непротиворечивые individual rows.
R5 заменяет inline-блоки данных на references к ресурсам, которые описывают это профессионально:
- Хочешь описать активность плана ухода → не пиши inline
activity.detail.{code, priority, status, description}, а сошлись наServiceRequest(для лабораторного запроса),Task(для action item),MedicationRequest(для рецепта). - Хочешь сказать кто записал/подтвердил наблюдение →
participant.actorreference, не два разных поля. - Хочешь привязать device к пациенту → отдельный
DeviceAssociation, не поле в Device.
Идея: каждое явление — одна сущность с одной ответственной resource shape. Inline-дублирование (тот же priority в CarePlan.activity.detail и ServiceRequest.priority) ломает интероп, потому что разные системы заполняют разные места.
Почему это не «улучшение всего и сразу»
Стоимость очевидна: одно “AI рекомендует досдать ферритин” в R4 — один inline-блок в CarePlan; в R5 — два ресурса (CarePlan + ServiceRequest) и transaction-bundle для атомарной записи. Для нашего случая это больше FHIR-write traffic и более сложный builder. Вопрос — оправдано ли.
R5 → R6: тренд продолжается
R6 в текущем ballot (hl7.fhir.core#6.0.0-ballot4, сгенерирован 14 мая 20262) — не релиз, не финальный. Может ещё измениться до публикации. Что можно зафиксировать как направление:
- Inline-данные → CodeableReference усиливается. AdverseEvent в R6:
suspectEntity.instance,contributingFactor,preventiveAction,mitigatingAction,supportingInfo— все из inline (BackboneElement или прямого CodeableConcept) переходят вCodeableReference. Dosage:siteтоже становитсяCodeableReference. - Большие inline-блоки разбиваются на новые типы данных. Dosage в R6 получает
DosageCondition,DosageDetails,DosageSafetyкак отдельные complex types, а multi-resource поля (maxDosePerPeriod,maxDosePerAdministration,maxDosePerLifetime) удалены из Dosage целиком — переезжают в новые structures. MedicationRequest/Dispense/Statement переходят на ссылку наDosageDetailsвместо rawDosage. - Резкое выделение domain-specific ресурсов из крупных контейнеров. InsurancePlan в R6 теряет
identifier,status,type,name,alias,period,ownedBy,administeredBy,coverage, и весьplansubstructure — это всё уезжает в новый ресурс InsuranceProduct. InsurancePlan становится тонким wrapper-ом, product-master живёт отдельно. Тот же паттерн что Device → DeviceAssociation в R5. - Новые ресурсы для специфичных concerns. В R6 появляется DeviceAlert (новый ресурс).
- Композитные backbone элементы вместо мелких. Composition.relatesTo в R6 — explicit BackboneElement (вместо generic
RelatedArtifact); новыйparticipantBackboneElement.
Источник4.
Направление консистентное с R4→R5: меньше inline, больше references на ресурсы с focused responsibility, новые domain-specific ресурсы выделяются из крупных контейнеров.
Где мы и что для нас значит
(Эта секция — про BloodGPT-specific implications. Выше — про сам стандарт.)
Где мы
BloodGPT использует FHIR R4 во всём стеке. Production — Google Healthcare API, FHIR stores привязаны к R4. Все builders (fhir-careplan-builder.ts, fhir-composition-builder.ts, и т.п.) пишут R4-shape JSON. Reference implementation hapi-fhir поддерживает оба, но dev/staging тоже на R4. Google Healthcare API поддерживает обе версии на vendor-уровне5 — миграция возможна на уровне инфры, но требует rewrite builders/readers под изменённые ресурсы.
CarePlan, ServiceRequest и Observation в R6 ballot4 — без существенных изменений по обсуждённым выше аспектам. Наш core стек R6-эволюцией не задевается напрямую. R6 для нас — наблюдаемый сигнал, не actionable: производственно мы R6 не увидим в ближайшие 1-2 года (даже R5 adoption ограниченный, R6 после релиза будет догонять).
Думать в reference-форме при дизайне
При проектировании новых FHIR-маппингов выгодно закладывать reference-форму с самого начала — то есть архитектурно решать что клиническая сущность будет жить в отдельном ресурсе со своим ID и Reference()-указанием на неё, а не inline-блоком внутри родительского ресурса.
Конкретный пример: «AI рекомендует досдать ферритин» можно описать двумя способами:
- (а) inline — в R4
CarePlan.activity.detailс полямиcode,priority,statusзаписанными внутри CarePlan. - (б) reference-form — отдельный
ServiceRequestresource +CarePlan.activity.referenceуказывающий на него.
(а) проще писать (один resource per analysis), но (б) — R5-обязательная форма (activity.detail в R5 удалён, остался только plannedActivityReference). Если уже сейчас в R4 пишем reference-форму — миграция на R5 cheap (тот же shape, поле переименовывается). Если пишем inline — придётся переделывать builders + читать всю историю при апгрейде.
Конкретные case’ы у нас
- CarePlan.activity для urgent tests / follow-up — в R4 у нас сейчас inline
activity.detail.priorityподход (план в zero-extensions-fhir и тикете BG-1250). Альтернатива —activity.reference→ отдельныйServiceRequestсpriority: "urgent"+intent: "proposal". R4 это разрешает (черезactivity.reference), R5 это требует. Если делать переход — это R5-ready. См. fhir-careplan, fhir-service-request. - AI-author — мы уже на
Organization/bloodgptчерезauthor[x]choice (см. authorship-organization-not-device). Этот choice-type без изменений в R5. - Provenance — meta.tag + Provenance ресурс (см. fhir-provenance) — R5 расширяет Provenance, но без breaking changes для нашего использования.
Открытые вопросы
- Когда мы готовы инвестировать в R5 миграцию. Сейчас живых внешних FHIR-consumer’ов нет, R4 покрывает наши сценарии. Триггер — первый клиент с requirement R5.
- Как делать transitional дизайн: писать R4 inline + R5-ready reference одновременно (двойная запись), или жёстко выбирать.
- Стоит ли уже сейчас на новых ресурсах (V2.5 rich-output, fhir-clinical-impression / fhir-service-request) использовать reference-форму, чтобы R5 миграция была дешевле.
Связано
- fhir-careplan — главный наш ресурс, у которого
activity.detailудалён в R5 - fhir-service-request — целевой ресурс для R5 reference-формы lab orders
- fhir-device — DeviceAssociation в R5 (нас не задевает напрямую — мы Device singleton используем как author)
- google-healthcare-api — поддерживает обе версии на vendor-уровне
- hapi-fhir — reference implementation R4/R5
- zero-extensions-fhir — наш design principle “чистый FHIR без extensions” живёт через обе версии
Источники
- FHIR R5 spec: https://hl7.org/fhir/R5/
- FHIR releases overview: https://hl7.org/fhir/directory.html
- Linear: BG-1250 (CarePlan urgent priority — extension vs standard discussion, R5-ready вариант)
Сноски
-
HL7 targeting late 2026 на final R6 при ожидании что ballot process идёт по графику. Historical precedent — R4 прошёл 3 ballot cycles за ~18 месяцев, поэтому реалистично R6 final ожидать mid-late 2027. Регуляторное следствие: если R6 опубликован до сентября 2026, USCDI 7-based US Core 10 — май 2027. https://build.fhir.org/ballot-intro.html. Цит. по сессии
ildar/29362bdd. ↩ -
HL7 FHIR build server,
https://build.fhir.org/— на 16 мая 2026 показываетhl7.fhir.core#6.0.0-ballot4 generated Thu, May 14, 2026. Это первый full ballot R6; normative ballot process начался в январе 2026 с ballot1 наhl7.org/fhir/6.0.0-ballot1. https://build.fhir.org/ + https://build.fhir.org/ballot-intro.html. Цит. по сессииildar/29362bdd. ↩ ↩2 -
HL7 FHIR R5 spec, “R4 → R5 differences” — официальный changelog по resource-level изменениям между R4 и R5. https://hl7.org/fhir/R5/diff.html ↩
-
HL7 FHIR build server, “R5 → R6 differences” — официальный changelog для R6 ballot4. https://build.fhir.org/diff.html. Цит. по сессии
ildar/29362bdd. ↩ -
Google Healthcare API documentation — FHIR R4 / R5 указывается при создании FHIR Store. https://cloud.google.com/healthcare-api/docs/concepts/fhir ↩