GCP-managed FHIR backend (плюс DICOM, HL7v2 — нам не критично). Альтернативы — hapi-fhir (self-hosted), Azure FHIR, Medplum. Выбран в session 871a7608 как primary FHIR storage для BloodGPT multi-tenant.
Структура
projects/{proj}/locations/{loc}/datasets/{datasetId}/fhirStores/{storeId}/fhir/{resourceType}/{id}
- Dataset — top-level container, изолированный namespace
- FHIR Store — внутри dataset, attached к FHIR R4/R5 версии
- Auth — OAuth2 через Workload Identity (GKE → GCP). Tokens истекают каждый час, нужен refresh per-call.
Использование в BloodGPT
- One dataset per Organization —
dataset: org-{orgId},fhirStore: fhir-r4. Физическая изоляция tenants. См. multi-tenant-fhir-storage. - Provisioning — Inngest function на event
org/createdсоздаёт dataset + FHIR store +Organization/bloodgpt(изначально планировалсяDevice/bloodgpt-ai, теперь Organization). Provisioning только для новых orgs — existing prod datasets безOrganization/bloodgptдают runtime error при write AI-content; manual fix черезgcloudсделан только для двух (см. fhir-organization). - HIPAA — BAA на GCP автоматически покрывает Healthcare API + Cloud SQL + GCS + GKE.
Capabilities
- FHIR R4 / R5 поддержка
- Built-in audit logging (Cloud Audit Logs)
- BigQuery streaming (для будущей analytics — стрим из FHIR в BQ)
- CMEK encryption
- VPC Service Controls (perimeter defense)
- Search API стандартный FHIR (R4 SearchParameter)
- Conditional create через
ifNoneExist
Gotchas / ограничения
Device в author[x] — отвергается
Verified в session c9560637 (Feb 17 2026): в author[x] choice-type Healthcare API принимает только Practitioner | Patient | RelatedPerson | Organization. Device — отвергается с validation failure. Это vendor-specific ограничение — FHIR R4 spec разрешает Device через author[x]. Pivot на fhir-organization (Organization-as-author). См. authorship-organization-not-device.
Ключевой урок: vendor-feasibility валидируется до finalize design decisions, не пост-фактум. См. multi-tenant-fhir-storage open question .
_include:iterate=Observation:has-member — поддерживается
Verified в c9560637. Google explicit declaration о поддержке :iterate modifier для R4/R5. Это значит Panel Observations с hasMember возвращаются в одном bundle:
GET DiagnosticReport?patient={pid}&date={date}
&_include=DiagnosticReport:result
&_include:iterate=Observation:has-member
Один запрос — DiagnosticReport → Panel Observations → Child Observations.
date search param на DiagnosticReport ищет по issued, не effectiveDateTime
Verified в c9560637 через эксперимент: ?date=2026-02-18 дал пустой результат, потому что issued: "2026-02-18", а кровь сдавали effectiveDateTime: "2025-12-18". Если нужно искать по дате забора — использовать другой параметр (effective) или search через _filter. Критично для use case “вернуть отчёт по дате забора”.
Patient/$everything работает, но возвращает много
Verified в c9560637: одна ваза анализа → 5279 строк JSON в $everything bundle. Не selective — возвращает всё связанное с Patient. Для use case “вернуть конкретный отчёт за дату” — overkill, нужен более точный запрос (например, DiagnosticReport?patient&date&_include).
Latency
FHIR search ~50-200ms vs SQL ~2-5ms. Для нашего pipeline (LLM-генерация секунды) это шум. Но для dashboard read-paths без LLM — может стать заметно. Mitigation strategy не финализирована (см. multi-tenant-fhir-storage).
OAuth refresh
Tokens из Workload Identity истекают через час. Subclass HealthcareFhirClient (extends FhirClient) refresh-ит per-call. Это потребовало перевести request, headers, baseUrl в base FhirClient class из private в protected.
Связано
- multi-tenant-fhir-storage — наша архитектура поверх Healthcare API
- hapi-fhir — alternative (используется на dev/staging как public test server)
- fhir-device — superseded из-за этого ограничения
- fhir-organization — current AI-author resource
- authorship-organization-not-device — actual decision triggered by this gotcha
- phi-in-fhir-not-sql — overall storage strategy
- fhir-bundle — transactional create, conditional create через
ifNoneExist - inngest — provisioning function
Источники
Сноски
-
GCP Healthcare API docs, accessed 2026-05-17, https://cloud.google.com/healthcare-api/docs. ↩
-
BAA on GCP, accessed 2026-05-17, https://cloud.google.com/security/compliance/hipaa-compliance. ↩
-
Сессия
ildar/871a7608, 2026-02-13 — ` (architecture decision). ↩ -
Сессия
ildar/c9560637, 2026-02-17 — ` (Device limit verified. ↩