В FHIR-store BloodGPT сосуществуют ресурсы разной природы: user-uploaded (PDF расшифровка, выписки от других клиник), AI-generated (наш Composition / CarePlan / ClinicalImpression), patient-reported (через chat / survey). Через resourceType их не различить — например, Composition может быть и нашей summary, и выпиской чужой клиники. Нужны явные discriminators для:
- Атрибутировать каждый resource источнику — когда написан, кем, на основе чего
- Фильтровать для consumer-side — «только AI», «только patient-reported», «только из chat», «полный audit конкретного write-event»
Рассматривали (source attribution alternatives)
- Разделение по resourceType (early option) — использовать отдельные FHIR resource types для AI и user-uploaded одного и того же концепта (например,
Compositionuser-uploaded vs пользовательскийBasic-ресурс для AI). Отвергнуто как нелогичное: один и тот же концепт (clinical document) в разных типах ломает FHIR-семантику и search; consumer-side тоже ломает (нужно знать оба типа для query «вся documentation patient»). evidence.detailнаCondition(initially proposed) — поле есть только на Condition, не работает для Medication / Allergy / Procedure / FamilyMemberHistory.containedDocumentReference — DocumentReference как embedded ресурс в каждом target. Дублирование: один import-документ → DocumentReference копируется в каждый созданный resource.- Custom
extensionна каждом resource. Технически работает (GCP Healthcare API поддерживает extensions в search через_include), но плодит non-standard FHIR — нарушает zero-extensions-fhir policy («минимизировать extensions, использовать стандартные слоты, где возможно»). meta.tag+meta.security+Provenanceresource — стандартные FHIR mechanisms, search-able через стандартные параметры. Выбрано.
Решение — четыре слоя
Оговорка: четыре слоя могут быть избыточно. Origin (Слой 1) + Provenance (Слой 4) — минимальный надёжный набор; source (Слой 2) и AIAST security (Слой 3) — оптимизации частых consumer-queries и industry-стандартная маркировка соответственно. Если в практике окажется что одного оригина хватает — слои 2-3 можно отложить. Зафиксировано как open question (см. ниже).
Слой 1: meta.tag origin — store-wide классификация
CodeSystem http://bloodgpt.com/fhir/CodeSystem/origin с тремя кодами. Применяется ко всем ресурсам:
| Origin | Когда | Lifecycle |
|---|---|---|
user-uploaded | Recognition pipeline пишет Observation / DiagnosticReport / Condition / MedicationStatement / Composition (incoming clinical doc) | Immutable после POST — без PUT’ов после создания |
external-data | (future) API-import от лаб-партнёров, Apple Health, других hospital’ов | Immutable |
ai-generated | save-fhir-ai-resources, V2.5 writeV25RichOutputToFhir, V0.5 Mastra write tools | Mutable — PUT-обновления норма (пере-интерпретация на каждом analysis run) |
Lifecycle rules детальнее — см. fhir-resource-origin-and-lifecycle.
Слой 2: meta.tag source — fine-grained source-of-truth для ai-generated
CodeSystem http://bloodgpt.com/fhir/CodeSystem/source. Применяется только к ресурсам с origin: ai-generated:
"meta": { "tag": [{
"system": "http://bloodgpt.com/fhir/CodeSystem/source",
"code": "health-chat" | "survey" | "document-import"
}]}Зачем отдельно от origin: даёт filter без extra _revinclude запроса. Например, ?_tag=source|health-chat&subject=Patient/X → все ресурсы пациента из chat-агента. Дублирующая информация с Provenance, но оптимизирует частые consumer-side queries.
Open question: в
meta.tagне зашита версия pipeline (промпт hash, model id, code revision), создавшая resource. Сейчас эту информацию несёт Provenance (черезagentиsignature/extension’ы), но не tag — поэтому нет дешёвого consumer-query вида «всё, что писал pipeline v2.5.3». TBD: добавить ли отдельныйmeta.tag pipeline-version|<semver>, или оставить Provenance как единственный источник истины для версионирования.
Слой 3: meta.security AIAST — HL7 standard для AI-asserted resources1
"meta": { "security": [{
"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationValue",
"code": "AIAST"
}]}AIAST — стандартный HL7 v3 ObservationValue code (не self-invented)1. Хранится в meta.security[] (integrity tag, не workflow tag), запрос через _security search param на любом resource type:
GET /ClinicalImpression?_security=AIAST → все AI-impressions
GET /Observation?_security=AIAST → AI-asserted observations
GET /?_security=AIAST → всё AI по серверу
GET /Observation?subject=Patient/123&_security:not=AIAST → trusted lab data, NO AI
Generalizable transferable pattern — public FHIR API без знания BloodGPT-specifics. Любой FHIR-клиент понимает.
Слой 4: Provenance resource — full audit chain
Один Provenance per write-event ссылается на все resources из этого события через target[]:
agent.who = Organization/bloodgpt(AI-author) — см. authorship-organization-not-devicerecordedtimestampentity.role: source+entity.whatссылка на DocumentReference (если source — документ); пусто для chat/surveytarget[]— все created resources в этом write event
Не для runtime filter — дорогой ?_revinclude=Provenance:target, не масштабируется. Для audit / compliance / legal queries (HIPAA reporting и т.п.).
Standard search param _revinclude=Provenance:target работает на GCP Healthcare API (verified).
См. fhir-provenance entity-page для деталей resource shape.
Соотношение слоёв
| Слой | Что отвечает | Search |
|---|---|---|
meta.tag origin | Природа ресурса (user vs AI vs external) | ?_tag=origin|ai-generated |
meta.tag source | Конкретный agent/path для AI-generated | ?_tag=source|health-chat |
meta.security AIAST | Integrity classification (AI-asserted) | ?_security=AIAST |
Provenance | Full audit chain (когда / кем / из чего / каким путём) | ?_revinclude=Provenance:target (только для audit) |
Все четыре могут coexist на одном ресурсе. Origin и source — разные codesystems, оба в meta.tag[]. Security и tag — два разных search params в FHIR.
Implementation status by writer
| Writer | origin tag | source tag | security: AIAST | Provenance |
|---|---|---|---|---|
Recognition pipeline (save-fhir-preliminary) | TBD — должен писать user-uploaded | N/A | N/A | TBD |
V2.5 AI builders (writeV25RichOutputToFhir) | TBD — должен писать ai-generated | TBD — document-import? | TBD | Создаёт Provenance per run (done) |
V0.5 Mastra write tools (recordSymptom/etc) | TBD — ai-generated | TBD — health-chat или survey | TBD | Должен — один Provenance per write-event |
| TextToFHIR document import (V2 port в TS) | TBD — ai-generated | TBD — document-import | TBD | TBD |
Сейчас ни один writer не выставляет meta.tag — gap зафиксирован в fhir-resource-origin-and-lifecycle раздел про gap. Migration policy: drop dev / bulk-tag stage / помечать с момента deploy.
Следствия
- Закрывает (separate det/AI) в fhir-modeling-ai-content — filter по
meta.tag.code = "document-import"даёт лабораторные данные;meta.tag.code = "health-chat"или"survey"— patient-reported. - Закрывает (AI-content audit marking) там же — Provenance + meta.tag = full audit (когда, кем, из какого документа). Versioning model/prompt — отдельная задача.
- Stale-detection прямолинеен — newer raw resource через
?_tag=origin\|user-uploaded&_lastUpdated=gt<...>. См. health-report-versioning-model. - Discharge summary case работает — пациент приносит выписку →
Composition + origin: user-uploaded; наша summary →Composition + origin: ai-generated; lookup?_tag=ai-generatedразличит. Не нужны костыли с identifier-сопоставлением.
Open questions
- Tagging not yet applied at writers — все writer’ы должны быть обновлены чтобы выставлять tags. Скоп ~1-2 дня + migration policy. Важно зашить в существующую миграцию (BG-1337 stage-2, координация с Vlad), иначе старые ресурсы остаются без origin/source и query’и фильтрации не работают на исторические данные.
- Provenance в
save-fhir-resources(analysis pipeline) — приоритет. Сейчас вся запись в FHIR происходит без Provenance: Composition + CarePlan + Observation*создаются и audit chain не закрывается. Это значит «4 слоя» сейчас фактически 1.5 (только tag/security; Provenance отсутствует там, где особенно нужен). План на ~30-40 строк, реализация отложена — но это не TBD-исследование, а уже понятная to-do единица работы. - CodeSystem URL
bloodgpt.com/fhir/CodeSystem/originи.../source— final URLs? (Параллельный вопрос про identifier namespace в health-report-versioning-model.) - 4-слойная избыточность — нужны ли все 4 слоя, или достаточно origin + Provenance? Source-tag и AIAST-security дублируют информацию из Provenance ради cheaper queries и industry-стандартной маркировки. Если consumer-side queries окажутся редкими — слои 2-3 кандидаты на упрощение.
- Pipeline version в tag — см. выше open question рядом с Слоем 2 (хранить ли семвер pipeline’а в
meta.tag pipeline-version, или достаточно Provenance). - 2-tier vs 3-tier для AI — origin tag единственный или дополнительный
tier: derived\|aggregate? Рекомендация: 2-tier пока нет use-case для 3-tier. См. fhir-resource-origin-and-lifecycle раздел про tier debate.
Отдельный (не tagging-вопрос):
- Composition «misleading completed» статус — recognition завершается со status=completed, но без AI-интерпретации. Промежуточный статус (
awaiting_interpretation)? Это не tagging-проблема, а отдельный вопрос про lifecycle Composition в pipeline — см. fhir-composition / fhir-resource-origin-and-lifecycle для extraction в отдельную decision-страницу при разрешении.
Связано
- fhir-resource-origin-and-lifecycle — lifecycle rules (immutability), enrichment legacy step retirement, stale-detection. Использует origin tag как discriminator.
- fhir-provenance — entity-page про Provenance resource shape
- authorship-organization-not-device —
Organization/bloodgptкакagent.whoв Provenance - zero-extensions-fhir — Provenance через standard pattern, не custom extension
- llm-numeric-codes-policy — связанная decision-page (LLM не доверять числовым кодам); вместе они задают V0.5 write tools architecture
- clinical-code-resolution — implementation pattern term→code; coding это что мы пишем в
codeполе, tagging — как помечаем ресурс целиком - clinical-record-reconciliation — dedup/reconciliation отдельно — что делать когда tag совпадает но resource по факту тот же
- fhir-modeling-ai-content — closes /
- health-report-vision — multi-source events (chat / survey / document import) enabled через эту tagging policy
- health-report-versioning-model — uses origin tag для stale-detection
Источники
Сноски
-
HL7 v3 ObservationValue codesystem (AIAST code), accessed 2026-05-17, https://terminology.hl7.org/CodeSystem-v3-ObservationValue.html. ↩ ↩2 ↩3
-
FHIR R4
Resource.meta.tag, accessed 2026-05-17, https://www.hl7.org/fhir/R4/resource.html#tag. ↩ -
FHIR R4
Resource.meta.security, accessed 2026-05-17, https://www.hl7.org/fhir/R4/resource.html#Meta. ↩ -
FHIR R4 Provenance, accessed 2026-05-17, https://hl7.org/fhir/R4/provenance.html. ↩
-
FHIR R4 DocumentReference, accessed 2026-05-17, https://hl7.org/fhir/R4/documentreference.html. ↩
-
Сессия
ildar/7ff79368, 2026-03-27 — (original decision. ↩