iT邦幫忙

2026 iThome 鐵人賽

DAY 24
0

摘要
Day 24 已經把 contract 裡的 versioned ValueSet canonical URL 推進到 terminology server $expand / $validate-code evidence。Day 24 不只補 terminology evidence,同時切出 request-scoped production readiness slice:sandbox auth boundary、non-PHI preflight、CapabilityStatement-based live interaction declarations、AuditEvent / Provenance readiness、PHI masking 與 retention evidence。

這和「能不能交換」有什麼關係?

Day 24 能回答:

這份 Bundle 的 LOINC / UCUM code,除了 local snapshot 之外,terminology server 是否也能提供 evidence?

但正式交換前還有一個更大的問題:

這個工具是否已經安全到可以接近 live sandbox exchange?

如果一個 quality gate 可以任意呼叫 sandbox endpoint、沒有 auth boundary、沒有 non-PHI guard、report 直接顯示 Patient identifier,也沒有 audit / retention evidence,那它仍然只是 demo。

Day 24 的目標不是變成 production exchange platform。
Day 24 的目標是:

MVP demo -> sandbox pre-exchange readiness gate

也就是說,今天新增的是「交換前安全邊界」:

  • 不是完整 SMART/OAuth。
  • 不是真實 Bundle submit。
  • 不是 persistent history。
  • 不是把 AuditEvent / Provenance 寫到外部 FHIR server。
  • 而是先讓 report 能證明:live sandbox checks 只有在 allowlist、auth mode、non-PHI guard 都通過時才會執行。

例如同一份 Bundle 進來時,Day 24 的判斷會是:

情境 結果
使用者沒有確認 synthetic / non-PHI sandbox preflight NOT_EVALUATED,不呼叫任何 sandbox endpoint
auth mode 是 none sandbox preflight NOT_EVALUATED,不呼叫 sandbox metadata
sandbox base URL 不在 allowlist sandbox preflight NOT_EVALUATED,不呼叫 HTTP client
allowlist、auth mode、non-PHI guard 都通過 只呼叫 /metadata,只讀 CapabilityStatement 宣告,不讀 Patient / Observation / DiagnosticReport

這讓 report 可以明確說明:

不是因為有 sandbox URL 就可以交換。
必須先通過 endpoint、auth、non-PHI 三個安全邊界。

今天的實作範圍

Day 24 的 request / report flow 變成:

使用者上傳 Bundle
   │
   ├─ 執行原本 JSON / FHIR / TW Core / contract rules
   │
   ├─ terminology server evidence
   │     ├─ ValueSet/$expand
   │     └─ ValueSet/$validate-code
   │
   ├─ live FHIR metadata evidence
   │     └─ GET {FHIR_BASE_URL}/metadata
   │
   └─ sandbox readiness slice
         │
         ├─ sandbox endpoint guard
         │     ├─ allowlist match
         │     ├─ reject userinfo / query / fragment
         │     ├─ reject private / link-local / metadata IP
         │     └─ redirect 不 follow
         │
         ├─ sandbox auth boundary
         │     └─ auth mode 不可為 none
         │
         ├─ non-PHI preflight
         │     ├─ 使用者必須確認 synthetic / non-PHI
         │     └─ Patient identifier / name / telecom / address / birthDate 會停用 live checks
         │
         ├─ CapabilityStatement interaction declarations
         │     ├─ Patient read / search-type
         │     ├─ Observation read / search-type
         │     └─ DiagnosticReport read / search-type
         │
         └─ request-scoped readiness evidence
               ├─ AuditEvent / Provenance readiness
               ├─ input SHA-256
               ├─ privacy masking categories
               └─ retention policy = request-scoped only / no persistent history

最後 Quality Test Report 會新增四個 evidence layer:

Quality Gate blocking result
   ├─ FHIR / TW Core / contract local rules
   ├─ Terminology server evidence
   ├─ Live FHIR metadata evidence
   └─ Sandbox readiness evidence
        ├─ non-PHI preflight
        ├─ sandbox auth evidence
        ├─ sandbox interaction declaration evidence
        ├─ privacy / retention evidence
        └─ AuditEvent / Provenance readiness evidence

Sandbox auth boundary 做到哪裡?

Day 24 不實作完整 SMART/OAuth authorization code flow。

今天只新增最小 auth boundary:

qualitygate.fhir.sandbox.auth-mode=none

首頁也新增 Sandbox auth mode

none
bearer_token_configured

policy 是:

Auth mode Sandbox preflight
none NOT_EVALUATED,不呼叫 sandbox metadata
bearer_token_configured 可進入下一層 guard

這不是在宣稱已完成 production auth。
bearer_token_configured 在 Day 24 只是一個 readiness evidence 狀態:

  • 不接收或保存 token value。
  • 不驗證 OAuth scope。
  • 不執行 SMART authorization code flow。
  • 不替 resource interaction 加上正式 Authorization header。

它只是避免 app 在沒有任何 auth boundary evidence 的情況下執行 live sandbox preflight。真正的 token flow、scope check、refresh token、client registration 與 SMART launch context 要留到 Day 25 之後處理。

Non-PHI preflight 做到哪裡?

Day 24 新增使用者確認:

Confirm this Bundle is synthetic/non-PHI test data

若未確認,sandbox preflight 直接:

NOT_EVALUATED

若已確認,系統仍會掃描 Patient 的直接識別欄位:

  • Patient.name
  • Patient.identifier.value
  • Patient.telecom
  • Patient.address
  • Patient.birthDate

如果發現這些欄位,non-PHI preflight 會回:

FAILED

但這個失敗不改變原本 Quality Gate 的 blocking outcome。
它只停用 live sandbox interaction preflight,避免疑似 PHI 被帶進 live checks。

Sandbox interaction preflight 做什麼?

Day 24 不呼叫:

  • /Patient
  • /Observation
  • /DiagnosticReport
  • search endpoint
  • create / update / delete
  • Bundle submit

它只呼叫 sandbox base URL 的:

GET {SANDBOX_FHIR_BASE_URL}/metadata

然後從 CapabilityStatement 檢查是否宣告:

Resource Interaction
Patient read
Patient search-type
Observation read
Observation search-type
DiagnosticReport read
DiagnosticReport search-type

這個 layer 的定位是:

live resource interaction readiness evidence
不是 live resource interaction execution

原因是 Day 24 還沒有完整 sandbox patient workflow、token handling、scope model、PHI transport policy,也沒有正式 audit retention。

Privacy / retention evidence 可以做到什麼?

Day 24 的 privacy evidence 是 report-level avoidance,不是正式 PHI de-identification pipeline。

也就是說,目前 report 避免顯示 direct Patient identifiers,並列出應被遮蔽或避免輸出的 field categories:

Patient.name
Patient.identifier.value
Patient.telecom
Patient.address
Patient.birthDate

這不代表系統已完成:

  • irreversible de-identification。
  • pseudonymization key management。
  • cross-resource identifier rewriting。
  • free-text PHI detection。
  • DICOM / attachment masking。

Day 24 能做到的是先把 report 邊界守住:

resource inventory 可以顯示 Patient count / resource id / evidence path。
report 不應直接輸出 Patient name、identifier value、telecom、address、birthDate。

Retention evidence 明確顯示:

request-scoped only; no persistent history

這表示目前版本不會把 uploaded Bundle、terminology response、FHIR metadata response、sandbox response 寫進資料庫。

AuditEvent / Provenance readiness 可以做什麼?

今天新增的是 request-scoped readiness evidence:

  • input SHA-256
  • selected contract id/version
  • gate outcome
  • rule count
  • terminology status
  • metadata status
  • sandbox preflight status

這讓 report 可以回答:

如果下一步要落地 AuditEvent / Provenance,最小 evidence 欄位在哪裡?

新增設定

qualitygate.fhir.sandbox.allowed-base-urls=
qualitygate.fhir.sandbox.allow-private-network=false
qualitygate.fhir.sandbox.auth-mode=none

預設空 allowlist 和 auth-mode=none 表示:

sandbox readiness evidence = NOT_EVALUATED
HTTP call = not called

今天新增的主要類別

  • SandboxFhirProperties
  • SandboxFhirEndpointGuard
  • SandboxFhirPreflightService
  • SandboxFhirPreflightResult
  • SandboxInteractionEvidence
  • NonPhiPreflightService
  • NonPhiPreflightResult
  • PrivacyRetentionService
  • PrivacyRetentionResult
  • AuditProvenanceReadinessService
  • AuditProvenanceReadinessResult

ValidationResult 也新增四個 request-scoped result:

  • nonPhiPreflightResult
  • sandboxFhirPreflightResult
  • privacyRetentionResult
  • auditProvenanceReadinessResult

測試重點

今天新增測試確認:

  • 未確認 non-PHI 時,live checks 不允許執行。
  • confirmed synthetic Bundle 且沒有直接 Patient identifiers 時,non-PHI preflight 通過。
  • Patient identifier / name 出現時,non-PHI preflight 失敗並停用 live checks。
  • sandbox base URL 未 allowlist 時不呼叫 HTTP client。
  • sandbox auth mode 為 none 時不呼叫 HTTP client。
  • non-PHI guard 未通過時不呼叫 HTTP client。
  • sandbox preflight 只呼叫 /metadata
  • sandbox preflight 不呼叫 /Patient/Observation/DiagnosticReport
  • CapabilityStatement 宣告 Patient / Observation / DiagnosticReport read / search-type 時產生 PASS evidence。

目前測試結果:

Tests run: 99, Failures: 0, Errors: 0, Skipped: 0

Day 24 完成後的邊界

完成後,專案的定位變成:

pre-exchange quality gate
   ├─ FHIR / TW Core validation
   ├─ partner contract rules
   ├─ contract lifecycle / compatibility
   ├─ unit normalization evidence
   ├─ terminology server evidence
   ├─ metadata preflight
   └─ sandbox readiness evidence

但它仍然不是:

  • production exchange platform。
  • full SMART/OAuth client。
  • live resource read/search executor。
  • Bundle submitter。
  • persistent audit log。
  • PHI repository。
  • retention deletion workflow。

下一步

之後預計從 Day 24 的 boundary 往下做:

  • 真正的 SMART/OAuth sandbox token flow。
  • non-PHI test patient fixture / workflow。
  • allowlisted live Patient / Observation / DiagnosticReport read/search execution checks。
  • FHIR AuditEvent / Provenance resource generation。
  • formal PHI masking policy。
  • database-backed persistent history。
  • retention deletion workflow。
  • deeper terminology governance,例如 inactive code policy、CodeSystem version、UCUM algebra。

Repository:twcore-data-quality-gate


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

尚未有邦友留言

立即登入留言