SMART Trust HCERT library tools
SMART Trust Tools
Wire format and payload models

Wire & payload models

The CBOR wire format is specified in CDDL (IETF RFC 8610). Payload models are derived mechanically from the WHO SMART FHIR logical models into a JSON-LD context, SHACL shapes and CDDL rules. Every example below is the Hepatitis B birth-dose certificate from smart-trust PR 129, which CI validates against all of these.

CDDL: HCERT envelope

api/cddl/hcert.cddl
; HCERT wire format (CBOR), RFC 8610 CDDL.
;
; Sources (WHO SMART Trust IG):
;   hcert_spec.md 3.2 CWT Claims, 4.2 Barcode          (deployed)
;   qr_code_generation.md 4-9 Steps 3-8                (PR 129)
;   RFC 9052 COSE_Sign1, RFC 8392 CWT
;
; Payload rules (dvc-min, ...) are generated from the FHIR logical models
; into models/generated/<ig>.cddl. CDDL has no import mechanism, so this file
; is concatenated with them for validation (tools/check-models/check_models.py).
;
; Draft for upstreaming: the envelope belongs in WorldHealthOrganization/
; smart-trust and the payload rules with their logical models (OI-19).

; Steps 5-8 output, before ZLIB/Base45. Issuers MUST tag. [STT-COS-001]
hc1-cose = #6.18(cose-sign1)

cose-sign1 = [
  protected: bstr .cbor protected-header,
  unprotected: unprotected-header,
  payload: bstr .cbor cwt-claims,
  signature: bstr,
]

; alg and kid in the protected header. [STT-COS-003]
protected-header = {
  1 => cose-alg,
  ? 4 => kid,
}

; kid MAY appear here instead; the protected one wins. [STT-COS-003]
unprotected-header = {
  ? 4 => kid,
}

cose-alg = es256 / ps256
es256 = -7    ; primary   [STT-COS-002]
ps256 = -37   ; secondary [STT-COS-002]

; First 8 bytes of SHA-256 over the DER DSC. [STT-KID-001]
kid = bstr .size 8

; ES256 signatures are fixed-width r||s. [STT-COS-005]
es256-signature = bstr .size 64

; CWT claim set. [STT-CWT-001]
cwt-claims = {
  ? 1 => tstr,             ; iss, alpha-2 when a country [STT-CWT-005]
  6 => numeric-date,       ; iat [STT-CWT-002]
  4 => numeric-date,       ; exp, mandatory [STT-CWT-003]
  -260 => hcert,
}

; HCERT requires integer NumericDate (RFC 8392 would also allow float).
numeric-date = int

; Issuance: exactly one subclaim entry, so hcert is a choice of
; single-entry maps. [STT-SEL-004] (OI-02)
; Subclaim registry (QR Code Generation 2.1). [STT-SEL-001]
; Adding a subclaim means adding an alternative here.
hcert = hcert-dcc / hcert-ddcc-vs / hcert-ddcc-tr / hcert-vhl / hcert-dvc / hcert-mtl

hcert-dcc = { 1 => any }               ; HCertDCC (EU DCC core data set)
hcert-ddcc-vs = { 3 => any }           ; DDCCCoreDataSetVS (proposed)
hcert-ddcc-tr = { 4 => any }           ; DDCCCoreDataSetTR (proposed)
hcert-vhl = { 5 => vhl-payload / vhl-uri } ; Verifiable Health Link [STT-VHL-002]
hcert-dvc = { -6 => dvc-min }          ; DVCMin, development range (OI-09, OI-17)
hcert-mtl = { -7 => any }              ; MedicationTreatmentLineMin, development range

; The SMART Health Links payload format that IHE VHL reuses, as a CBOR map:
; the primary form at key 5. [STT-VHL-001, STT-VHL-002] (OI-21, OI-23)
vhl-payload = {
  url: tstr,               ; https manifest URL (a FHIR List search)
  key: tstr .size 43,      ; 32 random bytes, base64url
  ? exp: int,              ; epoch seconds
  ? flag: tstr .regexp "L?P?",
  ? label: tstr .size (0..80),
  ? v: int,
  ? extension: { ? fhirBaseUrl: tstr, * tstr => any },
}

; IHE ITI-YY3's text form, still accepted on decode. [STT-VHL-003]
vhl-uri = tstr .regexp "vhlink:/[A-Za-z0-9_-]+"

; Context identifier and Base45 text (step 8). [STT-HC1-001, STT-B45-001]
hc1-string = tstr .regexp "HC1:[0-9A-Z $%*+./:-]+"

CDDL: payload rules, generated from the logical models

models/generated/trust-phw.cddl
; Generated by tools/lm-derive/lm_derive.py from FHIR logical models. Do not edit.
; Wire (CBOR) encoding of the payload logical models. Element names are
; the logical-model element names; primitive types carry the FHIR R5
; regex (RFC 8610 .regexp: XSD regex, implicitly anchored).

; http://smart.who.int/trust-phw/StructureDefinition/DVCMin (abstract)
dvc-min = {
  n: fhir-string,
  dob: fhir-date,
  s: fhir-code,  ; binding extensible http://hl7.org/fhir/administrative-gender
  nt: fhir-code,  ; binding extensible http://hl7.org/fhir/ValueSet/iso3166-1-3
  ? id: fhir-string,
  ? dt: fhir-code,  ; binding extensible http://terminology.hl7.org/ValueSet/v2-0203
  ? gn: fhir-string,
  vx: dvc-min-vaccine-details,
  v: fhir-string
}

; http://smart.who.int/trust-phw/StructureDefinition/DVCMinPreQual
dvc-min-pre-qual = {
  n: fhir-string,
  dob: fhir-date,
  s: fhir-code,  ; binding extensible http://hl7.org/fhir/administrative-gender
  nt: fhir-code,  ; binding extensible http://hl7.org/fhir/ValueSet/iso3166-1-3
  ? id: fhir-string,
  ? dt: fhir-code,  ; binding extensible http://terminology.hl7.org/ValueSet/v2-0203
  ? gn: fhir-string,
  vx: dvc-min-vaccine-details-pre-qual,
  v: fhir-string
}

; http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails (abstract)
dvc-min-vaccine-details = {
  vp: fhir-code,
  dv: fhir-date,
  bo: fhir-string,
  (is: fhir-id, ? cn: fhir-string // ? is: fhir-id, cn: fhir-string)  ; must-have-issuer-or-clinician-name
}

; http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetailsPreQual
dvc-min-vaccine-details-pre-qual = {
  vp: fhir-code,  ; binding required http://smart.who.int/pcmt-vaxprequal/ValueSet/PreQualProductIds
  dv: fhir-date,
  bo: fhir-string,
  (is: fhir-id, ? cn: fhir-string // ? is: fhir-id, cn: fhir-string)  ; must-have-issuer-or-clinician-name
}

; FHIR R5 primitive types (hl7.fhir.r5.core#5.0.0)
fhir-code = tstr .regexp "[^\\s]+( [^\\s]+)*"
fhir-date = tstr .regexp "([0-9]([0-9]([0-9][1-9]|[1-9]0)|[1-9]00)|[1-9]000)(-(0[1-9]|1[0-2])(-(0[1-9]|[1-2][0-9]|3[0-1]))?)?"
fhir-id = tstr .regexp "[A-Za-z0-9\\-\\.]{1,64}"
fhir-string = tstr .regexp "[\\s\\S]+"

CBOR example in diagnostic notation

Open the COSE bytes in cbor.me ↗

HC1 string (427 characters), then the COSE_Sign1 with each embedded layer decoded (<< >> marks a byte string holding CBOR).

HC1:NCFOXN%TSMAHN-HWM4/GR3.M: AQSSGAH9M91RIHF4NZKC7TFSTYUIBRR34Q-MPD ND%ERJC/HJI+8H-BI+8F.9HJ8 4GFDJ38KLUKAQC419%EEGJB/.D4-9MJCVPLW1KD0K9JAF/BT3EQ*9%NH7$K MI..3EEWVPMD+K$F91EF+:L*.9G%8M+8CNNE1J $47LPNV4YW8490-LN258VUUZX2LV34G8-:V4SI5SPDDK2XEPS5OH6CN5MZUCRQPK50F2TK1AVU%J6WLITK22VE TUVI13M9LREHOPJPQJVFKWOBY5PRALTIHR6L47CX53OVK682Y7IKUQK3.$AP.CE.CG%DAWCD8SSCH3ME6OHG5MNRH.8LTOT06Q/.F4KL4-GSP66G1%WR/+BG2M6ARB84I*2-J5-7J$*0XFSLLD
18([
  << {
  1: -7,
  4: h'58733e058aaa6621'
} >>,
  frozendict({}),
  << CWT claims, below >>,
  h'22a304f4c01aaf065393d86a7a7336cc98d58619031bb8e20179be244b2d4be8f2cbd62d4598d7c562848402496dd40f46cd0d060a5745da54d0a3ee75571f7f'
])
/ CWT claims /
{
  1: "XX",
  4: 1822206600,
  6: 1790670600,
  -260: {
    -6: {
      "n": "Chanthala SOUVANNALATH",
      "s": "female",
      "v": "1.0.0",
      "gn": "Mali SOUVANNALATH",
      "nt": "LAO",
      "vx": {
        "bo": "HEPB-2026-0914",
        "cn": "Dr Pimchanok WATTANA",
        "dv": "2026-09-28",
        "is": "org-xxa-provincial-hospital",
        "vp": "XM9V38"
      },
      "dob": "2026-09-28"
    }
  }
}

JSON-LD: the payload as linked data

Open in JSON-LD Playground ↗

Adding the generated context and a type to the payload's JSON view turns it into RDF. Each short element name expands to <StructureDefinition URL>#<element>.

{
  "@context": "trust-phw.context.jsonld",
  "@type": "DVCMin",
  "n": "Chanthala SOUVANNALATH",
  "s": "female",
  "v": "1.0.0",
  "gn": "Mali SOUVANNALATH",
  "nt": "LAO",
  "vx": {
    "bo": "HEPB-2026-0914",
    "cn": "Dr Pimchanok WATTANA",
    "dv": "2026-09-28",
    "is": "org-xxa-provincial-hospital",
    "vp": "XM9V38"
  },
  "dob": "2026-09-28"
}

Resulting triples (N-Triples)

_:N6cdc33655aea42f7a68a34cf47338c69 <http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#bo> "HEPB-2026-0914" .
_:N6cdc33655aea42f7a68a34cf47338c69 <http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#cn> "Dr Pimchanok WATTANA" .
_:N6cdc33655aea42f7a68a34cf47338c69 <http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#dv> "2026-09-28" .
_:N6cdc33655aea42f7a68a34cf47338c69 <http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#is> "org-xxa-provincial-hospital" .
_:N6cdc33655aea42f7a68a34cf47338c69 <http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#vp> "XM9V38" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#dob> "2026-09-28" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#gn> "Mali SOUVANNALATH" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#n> "Chanthala SOUVANNALATH" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#nt> "LAO" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#s> "female" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#v> "1.0.0" .
_:N73718689565746ca8e4fb11ba49628a2 <http://smart.who.int/trust-phw/StructureDefinition/DVCMin#vx> _:N6cdc33655aea42f7a68a34cf47338c69 .
_:N73718689565746ca8e4fb11ba49628a2 <http://www.w3.org/1999/02/22-rdf-syntax-ns#type> <http://smart.who.int/trust-phw/StructureDefinition/DVCMin> .
Generated context (trust-phw.context.jsonld)
{
  "@context": {
    "@version": 1.1,
    "xsd": "http://www.w3.org/2001/XMLSchema#",
    "DVCMin": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin"
    },
    "DVCMinPreQual": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinPreQual"
    },
    "DVCMinVaccineDetails": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails"
    },
    "DVCMinVaccineDetailsPreQual": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetailsPreQual"
    },
    "n": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#n"
    },
    "dob": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#dob"
    },
    "s": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#s"
    },
    "nt": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#nt"
    },
    "id": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#id"
    },
    "dt": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#dt"
    },
    "gn": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#gn"
    },
    "vx": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#vx",
      "@context": {
        "vp": {
          "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#vp"
        },
        "dv": {
          "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#dv"
        },
        "cn": {
          "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#cn"
        },
        "is": {
          "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#is"
        },
        "bo": {
          "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMinVaccineDetails#bo"
        }
      }
    },
    "v": {
      "@id": "http://smart.who.int/trust-phw/StructureDefinition/DVCMin#v"
    }
  }
}

Cardinality and FHIR primitive patterns are enforced; bindings are recorded (the PreQual value set has no published expansion); concept codes come from each element's ElementDefinition.code. To render or edit these shapes in a dedicated tool, load the TTL into SHACL Play!.

DVC HCERT Payload

abstract · logical model
ElementCard.TypeMeaningBindingConcept codes
n1..1stringName87226-7 ICVP.A9.DE.1
s1..1codeSexextensible administrative-genderICVP.A9.DE.3
v1..1stringVersionICVP.D5.DE.27
gn0..1stringParent or Guardian Name79183-0 ICVP.A9.DE.10 394619001
nt1..1codeNationalityextensible iso3166-1-369433-1 ICVP.A9.DE.8 223369002
vx1..1DVCMinVaccineDetailsVaccine Details
dob1..1dateDate of birth21112-8 ICVP.A9.DE.2 184099003
dt0..1codeNational ID Document Typeextensible v2-0203
id0..1stringNational Identification Document76435-7 ICVP.A9.DE.9 900000000000474003

DVCMinPreQual

concrete · logical model
ElementCard.TypeMeaningBindingConcept codes
n1..1stringName87226-7 ICVP.A9.DE.1
s1..1codeSexextensible administrative-genderICVP.A9.DE.3
v1..1stringVersionICVP.D5.DE.27
gn0..1stringParent or Guardian Name79183-0 ICVP.A9.DE.10 394619001
nt1..1codeNationalityextensible iso3166-1-369433-1 ICVP.A9.DE.8 223369002
vx1..1DVCMinVaccineDetailsPreQualVaccine Details
dob1..1dateDate of birth21112-8 ICVP.A9.DE.2 184099003
dt0..1codeNational ID Document Typeextensible v2-0203
id0..1stringNational Identification Document76435-7 ICVP.A9.DE.9 900000000000474003

DVC HCert Vaccine Details (Minimal)

abstract · logical model
ElementCard.TypeMeaningBindingConcept codes
bo1..1stringBatch No30959-1 ICVP.C5.DE.17
cn0..1stringName of supervising clinicianICVP.C5.DE.14
dv1..1dateDate of vaccination30952-6 ICVP.C5.DE.13
is0..1idCertificate issuer id (referenced organization)ICVP.C5.DE.15
vp1..1codeVaccine Product ID39236-5 ICVP.C5.DE.11 787859002

Invariant: must-have-issuer-or-clinician-name: Either issuer or clinicianName must be present

DVC HCERT Payload for PreQual DB

concrete · logical model
ElementCard.TypeMeaningBindingConcept codes
bo1..1stringBatch No30959-1 ICVP.C5.DE.17
cn0..1stringName of supervising clinicianICVP.C5.DE.14
dv1..1dateDate of vaccination30952-6 ICVP.C5.DE.13
is0..1idCertificate issuer id (referenced organization)ICVP.C5.DE.15
vp1..1codeVaccine Product IDrequired PreQualProductIds39236-5 ICVP.C5.DE.11 787859002

Invariant: must-have-issuer-or-clinician-name: Either issuer or clinicianName must be present