iT邦幫忙

2026 iThome 鐵人賽

DAY 22
0

摘要
Day 21 已經把 demo contract JSON 對齊 companion guide / trading partner agreement 的語境。Day 22 補上 contract schema validation、contract compatibility classification、unit normalization evidence、live FHIR /metadata CapabilityStatement evidence。

這和 Day 21 有什麼不同?

Day 21 的重點是:

這份 demo contract JSON 是否比較像真實合作方交換契約?

Day 22 的重點改成:

這份 contract 能不能被比較嚴格地載入?
契約升版會不會讓目前這份 Bundle 變成 blocking?
檢驗數值單位是否能產生可比較的 exchange evidence?
合作方 FHIR server metadata 是否和 selected contract 對得起來?

也就是說,Day 21 是把契約格式講清楚。
Day 22 是把契約品質、升版風險、單位正規化與 live metadata preflight 放進同一份 Quality Test Report。

目前定位更明確:

FHIR/TW Core validator = Profile validation
TW Lab Contract Gate = Profile validation + partner contract policy + upgrade evidence + metadata preflight

但 Day 22 仍然不是 production exchange platform。
它沒有讀取 Patient / Observation / DiagnosticReport endpoint,也沒有處理 OAuth、SMART、mTLS、PHI、audit retention 或 persistent history。

今天的實作範圍

今天新增或修改的範圍有:

  • src/main/java/com/twlab/qualitygate/validation/ExchangeContractService.java
  • src/main/java/com/twlab/qualitygate/validation/ContractComparisonResult.java
  • src/main/java/com/twlab/qualitygate/validation/CompatibilityClassification.java
  • src/main/java/com/twlab/qualitygate/validation/ContractDifference.java
  • src/main/java/com/twlab/qualitygate/validation/BundleParseService.java
  • src/main/java/com/twlab/qualitygate/validation/ValidationResult.java
  • src/main/java/com/twlab/qualitygate/validation/UnitNormalizationService.java
  • src/main/java/com/twlab/qualitygate/validation/UnitNormalizationEvidence.java
  • src/main/java/com/twlab/qualitygate/validation/FhirMetadataValidationService.java
  • src/main/java/com/twlab/qualitygate/validation/FhirMetadataValidationResult.java
  • src/main/java/com/twlab/qualitygate/validation/FhirMetadataHttpClient.java
  • src/main/java/com/twlab/qualitygate/validation/DefaultFhirMetadataHttpClient.java
  • src/main/java/com/twlab/qualitygate/web/ParseController.java
  • src/main/resources/templates/index.html
  • src/test/java/com/twlab/qualitygate/validation/ExchangeContractServiceTests.java
  • src/test/java/com/twlab/qualitygate/validation/ContractComparisonServiceTests.java
  • src/test/java/com/twlab/qualitygate/validation/UnitNormalizationServiceTests.java
  • src/test/java/com/twlab/qualitygate/validation/FhirMetadataValidationServiceTests.java
  • src/test/java/com/twlab/qualitygate/web/ParseControllerTests.java
  • README.md
  • docs/journal/20260823.md

Day 22 做四件事:

加強 uploaded contract schema validation。
替 contract comparison 加 compatibility classification 與差異摘要。
替 glucose mg/dL / mmol/L 加非阻擋 unit normalization evidence。
新增 optional FHIR base URL,只呼叫 /metadata 並解析 CapabilityStatement。

Contract schema validation 的用途是什麼?

Day 21 的 uploaded contract validation 已經檢查 required metadata、policy assertion、terminology policy 和 unknown rule code。
Day 22 再補上更接近 schema 的檢查。

現在 uploaded contract 會檢查:

欄位 / 區塊 Day 22 檢查
status 只能是 draftactiveretired
effectiveDate 必須是 ISO date
retireDate 若提供,必須是 ISO date,且不可早於 effectiveDate
retired contract 必須提供 retireDate
policyAssertions.obligation 只能是 SHALLSHOULDMAY
policyAssertions.severity 只能是 fatalerrorwarninginformation
enabled assertion id 必須對應已知 Java rule
terminologyPolicy.*ValueSetCanonical 必須是 versioned ValueSet canonical
allowedLoincCodes 不可空,代表 local expansion snapshot
allowedUcumCodes 不可空,代表 local expansion snapshot

這仍然不是正式 JSON Schema。
它也不是 FHIR IG package validation。

比較精準的說法是:

application-level contract schema validation

也就是本專案對 companion-contract JSON 的最小可信載入條件。

Contract compatibility classification 現在如何判斷?

Day 20 / Day 21 的 comparison 可以看出同一份 Bundle 在 v1.0 / v1.1 的結果不同。
但 report 還有一個問題:

這次 contract upgrade 對目前資料是不是 breaking?

Day 22 新增 CompatibilityClassification

Classification 意思
NON_BREAKING 沒有新增 blocking assertion,也沒有縮小 allowed code/unit set
POTENTIALLY_BREAKING 新增 SHALL/error/fatal assertion,或 allowed code/unit set 變窄
BREAKING_FOR_INPUT 目前這份 Bundle 在新版 contract 下新增 blocking rule failure
INCOMPATIBLE_CONTRACT contract/result 不足以比較

目前 demo 裡最重要的例子是:

v1.0 沒啟用 LAB-UNIT-002
v1.1 啟用 LAB-UNIT-002 as SHALL/error

如果 Bundle 的 UCUM system/code 正確:

classification = POTENTIALLY_BREAKING

因為新版 contract 增加了 blocking assertion,但這份資料沒有被擋。

如果 Bundle 的 UCUM system/code 錯誤:

classification = BREAKING_FOR_INPUT

因為新版 contract 對這份 input 新增了 blocking rule failure。

Unit normalization evidence 的用途是什麼?

Day 22 只做其中安全、可驗證、可展示的一小段:

glucose LOINC 2345-7
mg/dL <-> mmol/L

新增 UnitNormalizationService 會對 Bundle 裡的 Observation 產生:

  • rule id:UNIT-NORM-GLUCOSE-001
  • outcome:PASSNOT_EVALUATED
  • path
  • LOINC code
  • original value / unit
  • normalized value / unit
  • evidence text

例如:

95 mg/dL -> 5.27 mmol/L
5.3 mmol/L -> 95.50 mg/dL
(glucose conversion 使用 18.0182 作為 MVP 固定係數。)

這個 evidence 不會 block exchange。
它也不做:

  • clinical plausibility。
  • reference range 判斷。
  • 診斷建議。
  • full UCUM algebra。
  • terminology server validation。

所以它的定位是:

exchange comparison evidence
不是醫療判斷

Live FHIR metadata evidence 的用途是什麼?

Day 22 新增 optional FHIR base URL 欄位。
若使用者提供 base URL,後端只呼叫:

GET {FHIR_BASE_URL}/metadata

然後用 HAPI FHIR R4 parser 解析成:

CapabilityStatement

目前檢查:

  • response 是否能被解析成 FHIR R4 resource。
  • resourceType 是否為 CapabilityStatement
  • fhirVersion 是否和 selected contract 的 fhirVersion 一致。
  • 是否宣告 JSON format。
  • 是否有 implementationGuidesupportedProfile evidence。

HTTP client 的安全邊界:

  • timeout 設為 3 秒。
  • 不 follow redirect。
  • 只由 service 組出 /metadata URL。
  • 測試用 fake client 確認沒有呼叫 /Patient/Observation/DiagnosticReport

這不是 production conformance testing。
它只能回答:

這個 FHIR base URL 的 metadata 是否看起來和 selected contract 不衝突?

它不能回答:

這個合作方 API 是否真的能交換 Patient / Observation / DiagnosticReport?

首頁新增哪些 Report 區塊?

Day 22 首頁新增:

  • Optional FHIR base URL for live metadata check
  • Unit normalization evidence
  • Live FHIR metadata evidence
  • Compatibility classification
  • contract differences table

Quality Test Report 的 layer summary 也新增兩層:

Layer Blocking? 說明
Unit normalization evidence No 只做 glucose mg/dL / mmol/L exchange evidence
Live FHIR metadata evidence No 只呼叫 /metadata,不碰 PHI resource

這兩層都不會改變原本 Quality Gate blocking policy。
Quality Gate 仍由 JSON parse、FHIR R4 parse、Bundle gate、FHIR validation、TW Core validation、SHALL/error contract rule failures 決定。

自動化驗證

本機 Maven 測試:

./mvnw test

結果:

Tests run: 80, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS

Day 22 新增或調整的測試確認:

  • uploaded contract invalid status 會被拒絕。
  • invalid ISO date 會被拒絕。
  • empty allowed UCUM snapshot 會被拒絕。
  • unversioned ValueSet canonical 會被拒絕。
  • v1.0 -> v1.1 新增 blocking assertion 時會標成 POTENTIALLY_BREAKING
  • 同一份 UCUM 錯誤 Bundle 在新版 contract 下新增 blocking failure 時會標成 BREAKING_FOR_INPUT
  • glucose 95 mg/dL 會產生 5.27 mmol/L normalization evidence。
  • glucose 5.3 mmol/L 會產生 95.50 mg/dL normalization evidence。
  • unsupported LOINC/unit 會回 NOT_EVALUATED
  • valid R4 CapabilityStatement metadata 會通過 metadata evidence check。
  • FHIR version mismatch 會回 NOT_EVALUATED
  • invalid JSON / non-CapabilityStatement / timeout 都會回清楚 evidence。
  • live metadata test 確認沒有呼叫 Patient / Observation / DiagnosticReport endpoint。
  • Controller 首頁顯示 FHIR base URL、unit normalization、live metadata、compatibility classification。

本機啟動確認

啟動:

./mvnw spring-boot:run
http://localhost:8080/ -> 200

並確認首頁包含:

Optional FHIR base URL for live metadata check

今天完成了什麼

  • ExchangeContractService 補強 uploaded contract application-level schema validation。
  • 新增 CompatibilityClassification
  • 新增 ContractDifference
  • ContractComparisonResult 新增 classification 與 differences。
  • 新增 UnitNormalizationService
  • 新增 UnitNormalizationEvidence
  • BundleParseService 成功解析 Bundle 後會產生 unit normalization evidence。
  • ValidationResult 新增 unit normalization 與 FHIR metadata evidence。
  • 新增 FhirMetadataValidationService
  • 新增 FhirMetadataHttpClient 與 default Java HTTP client。
  • ParseController 新增 optional fhirBaseUrl input。
  • 首頁新增 unit normalization、live metadata、compatibility report。
  • README 更新 Day 22 MVP 已完成項目與 remaining gap。
  • 新增並整理本 journal。
  • ./mvnw test 通過,測試數 80。
  • 18080 dev server 已停止。

Day 22 尚未處理:

  • Formal JSON Schema file。
  • Formal FHIR IG package。
  • Full terminology server $expand / $validate-code
  • Full UCUM algebra / parser。
  • Clinical plausibility checks。
  • Live Patient / Observation / DiagnosticReport lookup。
  • SMART / OAuth / mTLS。
  • Endpoint allowlist / SSRF production hardening。
  • Consent / Provenance / AuditEvent production workflow。
  • PHI masking / retention / persistent history。

目前的 MVP 進度:

validation-flow
├─ JSON parse                                  完成
├─ FHIR R4 parse                               完成
├─ FHIR R4 validation                          完成
├─ TW Core validation / safe NOT_EVALUATED      完成
├─ Partner exchange contract loading
│  ├─ demo-lab-v1.0.json                       完成
│  ├─ demo-lab-v1.1.json                       完成
│  ├─ policyAssertions                         完成
│  ├─ obligation / severity                    完成
│  ├─ lifecycle metadata                       完成
│  ├─ terminologyPolicy metadata               完成
│  ├─ allowedLoincCodes local snapshot          完成
│  ├─ allowedUcumCodes local snapshot           完成
│  ├─ optional uploaded contract                完成
│  └─ application-level schema validation       完成
├─ Exchange contract rules
│  ├─ LAB-REF-001                              完成並由 contract 啟用
│  ├─ LAB-REF-002                              完成並由 contract 啟用
│  ├─ LAB-REF-003                              完成並由 contract 啟用
│  ├─ LAB-CODE-001                             完成,允許值由 contract 提供
│  ├─ LAB-UNIT-001                             完成並由 contract 啟用
│  └─ LAB-UNIT-002                             完成,允許值由 contract 提供
├─ Quality Gate
│  ├─ SHALL error/fatal blocking                完成
│  └─ SHOULD/MAY warning behavior               完成
├─ Contract comparison
│  ├─ comparison service test                   完成
│  ├─ homepage comparison display               完成
│  ├─ compare checkbox                          完成
│  ├─ uploaded 2+ version comparison             完成
│  ├─ upgrade blocker evidence display          完成
│  ├─ compatibility classification              完成
│  └─ contract difference summary               完成
├─ Unit normalization evidence
│  ├─ glucose mg/dL -> mmol/L                   完成
│  ├─ glucose mmol/L -> mg/dL                   完成
│  └─ unsupported code/unit NOT_EVALUATED        完成
├─ Live FHIR API metadata
│  ├─ optional FHIR base URL                    完成
│  ├─ GET /metadata only                         完成
│  ├─ CapabilityStatement parse                  完成
│  ├─ fhirVersion alignment                      完成
│  ├─ JSON format evidence                       完成
│  └─ IG / profile declaration evidence          完成
├─ Scenario test pack
│  ├─ v1.0 / v1.1 representative cases          完成 4 例
│  └─ SHOULD warning behavior                   完成 1 例
├─ Homepage Quality Test Report                 完成
└─ Reproducible delivery
   ├─ Dockerfile                                完成最小版
   ├─ Docker Compose                            完成最小版並驗證啟動
   └─ GitHub Actions CI                         完成最小版

下一步預計處理:

production security and live exchange track

Repository:twcore-data-quality-gate


上一篇
Day21 - 把 Demo Contract 對齊真實 FHIR 交換契約語境
下一篇
Day23 - Terminology Server $expand / $validate-code Evidence
系列文
醫療資料通過標準驗證,就真的能交換嗎?——30 天打造 TW Core 資料品質閘門23
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言