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.actor reference, не два разных поля.
  • Хочешь привязать 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 вместо raw Dosage.
  • Резкое выделение domain-specific ресурсов из крупных контейнеров. InsurancePlan в R6 теряет identifier, status, type, name, alias, period, ownedBy, administeredBy, coverage, и весь plan substructure — это всё уезжает в новый ресурс InsuranceProduct. InsurancePlan становится тонким wrapper-ом, product-master живёт отдельно. Тот же паттерн что Device → DeviceAssociation в R5.
  • Новые ресурсы для специфичных concerns. В R6 появляется DeviceAlert (новый ресурс).
  • Композитные backbone элементы вместо мелких. Composition.relatesTo в R6 — explicit BackboneElement (вместо generic RelatedArtifact); новый participant BackboneElement.

Источник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 — отдельный ServiceRequest resource + 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” живёт через обе версии

Источники

Сноски

  1. 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.

  2. 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

  3. HL7 FHIR R5 spec, “R4 → R5 differences” — официальный changelog по resource-level изменениям между R4 и R5. https://hl7.org/fhir/R5/diff.html

  4. HL7 FHIR build server, “R5 → R6 differences” — официальный changelog для R6 ballot4. https://build.fhir.org/diff.html. Цит. по сессии ildar/29362bdd.

  5. Google Healthcare API documentation — FHIR R4 / R5 указывается при создании FHIR Store. https://cloud.google.com/healthcare-api/docs/concepts/fhir