摘要
Day 4 把 TW Core validation 降級處理為NOT_EVALUATED。Day 5 實測 HAPI/HL7 package cache 能不能載入tw.gov.mohw.twcore#1.0.0,並確認三個 MVP Profile canonical 是否能從 package 中讀到。
Day 4 已經回答:
如果 TW Core 未正式驗證,畫面應該怎麼誠實顯示?
Day 5 要回答的是另一個問題:
HAPI 到底能不能在本機拿到 TW Core IG v1.0.0 的 package 與 Profile 定義?
這兩件事不同。
Day 4 是狀態設計,Day 5 是載入實測。
如果 package loading 失敗,下一步就不該急著寫 Profile validation,因為 validation support chain 連 Profile 來源都還不穩。
如果 package loading 成功,也不能直接把 TW Core validation 顯示成 PASSED。它只代表系統已經能讀到 Profile 定義,還沒有真的拿 Bundle 裡的 Patient、Observation、DiagnosticReport 去跑 Profile validation。
Day 5 固定測試這個 package:
Package ID: tw.gov.mohw.twcore
Package version: 1.0.0
Package coordinate: tw.gov.mohw.twcore#1.0.0
Canonical base: https://twcore.mohw.gov.tw/ig/twcore
FHIR version: R4 4.0.1
並檢查三個 MVP Profile canonical:
| Resource | Canonical |
|---|---|
| Patient | https://twcore.mohw.gov.tw/ig/twcore/StructureDefinition/Patient-twcore |
| Observation | https://twcore.mohw.gov.tw/ig/twcore/StructureDefinition/Observation-simple-twcore |
| DiagnosticReport | https://twcore.mohw.gov.tw/ig/twcore/StructureDefinition/DiagnosticReport-twcore |
Day 5 新增的流程在合法 Bundle 通過前置 gate 之後:
Bundle 已通過 JSON / FHIR R4 parse / Resource Type Gate
↓
TwCoreValidationService
↓
TwCorePackageProbe
↓
FilesystemPackageCacheManager
↓
loadPackage("tw.gov.mohw.twcore", "1.0.0")
↓
檢查 package metadata
↓
檢查三個 StructureDefinition canonical
↓
回報 package loading probe 結果
↓
TW Core validation 仍顯示 NOT_EVALUATED
重點是最後一步仍然是 NOT_EVALUATED。
因為 Day 5 的成果是:
package 可載入,Profile canonical 找得到。
不是:
Bundle 已通過 TW Core Profile validation。
Day 5 新增三個小型類別:
src/main/java/com/twlab/qualitygate/validation
├─ TwCorePackageProbe.java
├─ TwCorePackageProbeResult.java
└─ HapiTwCorePackageProbe.java
TwCorePackageProbe
public interface TwCorePackageProbe {
TwCorePackageProbeResult probe();
}
抽成介面的原因不是為了複雜抽象,而是測試需要控制 probe 成功或失敗,不應該讓單元測試真的依賴 package server。
TwCorePackageProbeResult
probe result 回報四個資訊:
public record TwCorePackageProbeResult(
boolean loaded,
String category,
String message,
List<String> missingCanonicals
) {}
其中 category 用來協助排查:
| category | 意義 |
|---|---|
LOADED |
package 載入成功,必要 canonical 都找得到 |
DEPENDENCY |
HAPI/HL7 package loading 相關 dependency 不完整 |
PACKAGE_SOURCE |
package server、cache 或 package 來源問題 |
TERMINOLOGY |
terminology 相關問題 |
CANONICAL_RESOLUTION |
package 已載入,但必要 canonical 找不到 |
VALIDATION_SUPPORT_CONFIG |
其他 validation support 設定問題 |
FilesystemPackageCacheManager 載入 TW Core packageDay 5 的實際載入程式如下:
FilesystemPackageCacheManager packageCacheManager =
new FilesystemPackageCacheManager.Builder()
.build();
NpmPackage npmPackage = packageCacheManager.loadPackage(
TwCoreValidationResult.PACKAGE_ID,
TwCoreValidationResult.PACKAGE_VERSION
);
這裡使用 HAPI 帶入的 HL7 utilities package cache。實測後 package 會被放在本機 FHIR package cache 中。
載入 package 後,Day 5 確認 Profile 定義可讀:
private static final List<String> REQUIRED_CANONICALS = List.of(
CANONICAL_BASE + "/StructureDefinition/Patient-twcore",
CANONICAL_BASE + "/StructureDefinition/Observation-simple-twcore",
CANONICAL_BASE + "/StructureDefinition/DiagnosticReport-twcore"
);
每個 canonical 都用 npmPackage.loadByCanonical(canonical) 檢查。
只要有一個找不到,就回報 CANONICAL_RESOLUTION,代表 TW Core package 不可用於 MVP。
TwCoreValidationService
TwCoreValidationService 現在會在合法 Bundle 通過前置 gate 後執行 probe。
回傳狀態仍然是 NOT_EVALUATED:
if (probeResult.loaded()) {
return TwCoreValidationResult.notEvaluated(
probeResult.message()
+ " Day 5 僅完成 package loading probe,尚未執行正式 TW Core Profile validation,不冒充 Profile 通過。"
);
}
這裡刻意不新增 PASSED,避免把 package loading 成功誤解成資料通過 TW Core。
package loading 不應該每次上傳 Bundle 都重新執行。
因此 TwCoreValidationService 會快取第一次 probe 結果:
private volatile TwCorePackageProbeResult packageProbeResult;
這樣上傳第二份 Bundle 時,不會重複下載或讀取 package。
Day 5 用本機 probe 實際跑過一次,結果如下:
loaded=true
category=LOADED
message=TW Core package loading probe 成功:tw.gov.mohw.twcore#1.0.0,canonical base https://twcore.mohw.gov.tw/ig/twcore,FHIR R4 4.0.1 confirmed,已找到 Patient、Observation-simple、DiagnosticReport StructureDefinition。
missing=[]
這代表:
tw.gov.mohw.twcore#1.0.0 可以被本機 HAPI/HL7 package cache 載入。4.0.1。
使用 valid-minimal-lab-bundle.json 驗證時,頁面會顯示:
JSON parse: PASSED
FHIR R4 parse: PASSED
Resource Type Gate: PASSED
FHIR R4 validation: PASSED
TW Core validation: NOT_EVALUATED
tw.gov.mohw.twcore#1.0.0
TW Core package loading probe 成功:tw.gov.mohw.twcore#1.0.0...
Day 5 僅完成 package loading probe,尚未執行正式 TW Core Profile validation,不冒充 Profile 通過。

這張圖代表:
package loading 成功,但 TW Core validation 仍未執行。
Day 5 另外新增三份 fixture,為 Reference rule 做準備。
| Fixture | 目的 |
|---|---|
valid-internal-reference.json |
Bundle 內 reference 都存在 |
missing-internal-reference.json |
Observation.subject 指向不存在的 Patient |
external-http-reference.json |
使用外部 HTTP reference |
今天只確認這三份資料可以被現有 parser 與 inventory 穩定讀取。
例如三份資料都應該能顯示:
Patient: 1
Observation: 1
DiagnosticReport: 1
Not evaluated: 0

注意:畫面目前不會顯示 LAB-REF-001 failed,且這三份 fixture 在 Day 5 的畫面結果會很相似,因為目前尚未實作 Reference rule。它們的價值是先固定後續要使用的正反例素材。
| 項目 | Day 4 | Day 5 |
|---|---|---|
| 主要問題 | 尚未驗證時怎麼誠實顯示 | package 能不能真的載入 |
| 新增核心 | TwCoreValidationResult、TwCoreValidationService |
TwCorePackageProbe、HapiTwCorePackageProbe |
| TW Core 狀態 | NOT_EVALUATED |
仍是 NOT_EVALUATED |
| 差異 | 有固定 package metadata 與降級原因 | message 進一步包含 package loading probe 實測結果 |
| 是否正式 Profile validation | 否 | 否 |
| 是否準備 Reference fixture | 否 | 是 |
真正的差異是:
Day 4 的
NOT_EVALUATED是「未穩定載入 package」;Day 5 的NOT_EVALUATED是「package loading 已實測成功,但 Profile validation 尚未執行」。
指令:
./mvnw test
測試結果:
Tests run: 16, Failures: 0, Errors: 0, Skipped: 0
BUILD SUCCESS
Day 5 測試重點:
NOT_EVALUATED。NOT_EVALUATED,並顯示失敗分類。loaded=true 寫成 TW Core validation passedloaded=true 只代表 package 載入成功,不代表 Bundle 符合 TW Core Profile。
package 成功載入但找不到 StructureDefinition 時,應該歸類為 CANONICAL_RESOLUTION。
單元測試使用 fake probe 控制成功與失敗情境。真實 package loading probe 可以用手動實測或整合測試補充,不應讓一般單元測試因網路不穩而失敗。
missing-internal-reference.json 目前不會觸發 LAB-REF-001,後續才會建立交換契約規則。
probe 結果已在 service 中快取。如果後續要支援切換 package version,才需要重新設計 cache key。
TwCorePackageProbe 介面。TwCorePackageProbeResult。HapiTwCorePackageProbe。FilesystemPackageCacheManager 實測載入 tw.gov.mohw.twcore#1.0.0。4.0.1。TwCoreValidationService 接入 package loading probe,並快取 probe 結果。NOT_EVALUATED,不冒充 Profile validation 通過。Day 5 尚未處理:
LAB-REF-001、LAB-REF-002、LAB-REF-003。後續分層預計會變成:
quality-gate
├─ parser
├─ fhir-r4-validator
├─ resource-inventory
├─ tw-core-package-probe
├─ tw-core-validator
├─ reference-checker
├─ contract-rule
└─ report
Repository:twcore-data-quality-gate