The EUDI ETSI TS 119 602 Data Model module provides a Kotlinx serialization implementation of the data structures defined in ETSI TS 119 602 - Lists of Trusted Entities (LoTE).
This module enables serialization and deserialization of LoTE documents to/from JSON format, ensuring compliance with the ETSI TS 119 602 JSON schema.
Add the following to your build.gradle.kts:
dependencies {
implementation("eu.europa.ec.eudi:etsi-119602-data-model:$version")
}import eu.europa.ec.eudi.etsi119602.datamodel.ListOfTrustedEntities
import kotlinx.serialization.json.Json
val json = """
{
"ListAndSchemeInformation": {
"LoTEVersionIdentifier": "1.1.1",
"LoTESequenceNumber": 1,
"LoTEType": "http://uri.etsi.org/19602/LoTEType",
"SchemeOperatorName": [{"lang": "en", "value": "Example Operator"}],
"SchemeName": [{"lang": "en", "value": "Example Scheme"}],
"SchemeInformationURI": [{"lang": "en", "uriValue": "https://example.com/scheme"}],
"StatusDeterminationApproach": "http://uri.etsi.org/19602/StatusDetn/EU",
"SchemeTypeCommunityRules": ["http://uri.etsi.org/19602/schemerules/EU"],
"SchemeTerritory": "EU",
"ListIssueDateTime": "2024-01-01T00:00:00Z",
"NextUpdate": {"dateTime": "2025-01-01T00:00:00Z"}
},
"TrustedEntitiesList": [
{
"TrustedEntityInformation": {
"TEName": [{"lang": "en", "value": "Example Provider"}],
"TEAddress": {
"TEPostalAddress": [{"lang": "en", "StreetAddress": "Example St", "Locality": "Brussels", "Country": "BE"}],
"TEElectronicAddress": [{"lang": "en", "uriValue": "https://example.com"}]
},
"TEInformationURI": [{"lang": "en", "uriValue": "https://example.com/info"}]
},
"TrustedEntityServices": [
{
"ServiceInformation": {
"ServiceName": [{"lang": "en", "value": "PID Issuance"}],
"ServiceDigitalIdentity": {
"X509Certificates": [{"encoding": "base64", "val": "MIID..."}]
},
"ServiceTypeIdentifier": "http://uri.etsi.org/19602/SvcType/PID/Issuance",
"ServiceStatus": "http://uri.etsi.org/19602/Status/granted"
}
}
]
}
]
}
""".trimIndent()
val jsonFormat = Json { ignoreUnknownKeys = true }
val lote = jsonFormat.decodeFromString<ListOfTrustedEntities>(json)
// Access LoTE data
println("LoTE Version: ${lote.schemeInformation.loteVersionIdentifier}")
println("Trusted Entities: ${lote.entities?.size}")import eu.europa.ec.eudi.etsi119602.datamodel.*
import kotlinx.serialization.json.Json
// Create LoTE structure
val schemeInfo = ListAndSchemeInformation(
loteVersionIdentifier = ETSI19602.LOTE_VERSION,
loteSequenceNumber = ETSI19602.INITIAL_SEQUENCE_NUMBER,
loteType = URI(ETSI19602.LOTE_TYPE_URI),
schemeOperatorName = listOf(MultilanguageString("en", "Example Operator")),
schemeName = listOf(MultilanguageString("en", "Example Scheme")),
schemeInformationURI = listOf(MultiLanguageURI("en", URI("https://example.com/scheme"))),
statusDeterminationApproach = URI(ETSI19602.EU_PID_PROVIDERS_STATUS_DETERMINATION_APPROACH),
schemeTypeCommunityRules = listOf(URI(ETSI19602.EU_PID_PROVIDERS_SCHEME_COMMUNITY_RULES)),
schemeTerritory = CountryCode("EU"),
listIssueDateTime = LoTEDateTime.now(),
nextUpdate = NextUpdate(dateTime = LoTEDateTime.now().plusDays(365))
)
val lote = ListOfTrustedEntities(schemeInformation = schemeInfo, entities = emptyList())
// Serialize to JSON
val jsonFormat = Json { prettyPrint = true }
val json = jsonFormat.encodeToString(ListOfTrustedEntities.serializer(), lote)The module implements the complete ETSI TS 119 602 data model:
Metadata about the LoTE document:
loteVersionIdentifier: Version of the LoTE specificationloteSequenceNumber: Sequence number for versioningloteType: Type identifier for the LoTEschemeOperatorName: Name of the scheme operatorschemeInformationURI: URI to scheme informationstatusDeterminationApproach: Approach for status determinationschemeTypeCommunityRules: Applicable community rulesschemeTerritory: Territory covered by the schemelistIssueDateTime: Issue date/time of the LoTEnextUpdate: Expected next update date/time
Represents a trusted entity (e.g., PID Provider, Wallet Provider):
information: Entity details (name, address, URIs)services: List of services provided by the entity
Represents a service provided by a trusted entity:
information: Service details (name, digital identity, type, status)history: Historical service information
Digital identity of a service:
x509Certificates: X.509 certificatesx509SubjectNames: X.509 subject namespublicKeyValues: Public key valuesx509SKIs: X.509 Subject Key IdentifiersotherIds: Other identifiers
MultilanguageString: Localized text with language tagMultiLanguageURI: Localized URI with language tagPostalAddress: Structured postal addressLoTEDateTime: Date/time in ETSI formatCountryCode: ISO 3166-1 alpha-2 country codeURI: URI wrapper type
graph TD
A[LoTE JSON Document] --> B[Kotlinx Serialization]
B --> C[ListOfTrustedEntities]
C --> D[ListAndSchemeInformation]
C --> E[TrustedEntitiesList]
E --> F[TrustedEntity]
F --> G[TrustedEntityInformation]
F --> H[TrustedEntityServices]
H --> I[TrustedEntityService]
I --> J[ServiceInformation]
J --> K[ServiceDigitalIdentity]
K --> L[X509Certificates]
style A fill:#e3f2fd
style C fill:#fff3e0
style F fill:#f3e5f5
style K fill:#c8e6c9
The module is designed to be compatible with the ETSI TS 119 602 JSON Schema.
The module supports all ETSI TS 119 602 LoTE types:
| LoTE Type | Constant | Description |
|---|---|---|
| PID Providers | ETSI19602.EU_PID_PROVIDERS_LOTE |
List of PID providers notified by Member States |
| Wallet Providers | ETSI19602.EU_WALLET_PROVIDERS_LOTE |
List of wallet providers notified by Member States |
| WRPAC Providers | ETSI19602.EU_WRPAC_PROVIDERS_LOTE |
List of wallet relying party access certificate providers |
| WRPRC Providers | ETSI19602.EU_WRPRC_PROVIDERS_LOTE |
List of wallet relying party registration certificate providers |
| PubEAA Providers | ETSI19602.EU_PUB_EAA_PROVIDERS_LOTE |
List of public sector EAA providers |
| Registrars & Registers | ETSI19602.EU_REGISTRARS_AND_REGISTERS_LOTE |
List of registrars and registers |
The 119602-data-model module is a Kotlin Multiplatform (KMP) module.
| Platform | Status |
|---|---|
| commonMain | β Core data types and serialization |
| jvmAndAndroidMain | β JVM/Android extensions |
dependencies {
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:$kotlinxSerializationVersion")
}kotlinx-serialization-core(viakotlinx-serialization-json)
val lote: ListOfTrustedEntities = // ... deserialize from JSON
// Get scheme information
val schemeInfo = lote.schemeInformation
println("Scheme: ${schemeInfo.schemeName.firstOrNull()?.value}")
println("Operator: ${schemeInfo.schemeOperatorName.firstOrNull()?.value}")
println("Territory: ${schemeInfo.schemeTerritory.code}")
// Iterate over trusted entities
lote.entities?.forEach { entity ->
println("Entity: ${entity.information.name.firstOrNull()?.value}")
entity.services.forEach { service ->
println(" Service: ${service.information.name.firstOrNull()?.value}")
println(" Type: ${service.information.typeIdentifier?.value}")
println(" Status: ${service.information.status?.value}")
}
}val service: TrustedEntityService = // ... get service
// Access X.509 certificates
val certificates = service.information.digitalIdentity.x509Certificates
certificates?.forEach { cert ->
println("Certificate encoding: ${cert.encoding}")
println("Certificate value: ${cert.val}")
}
// Access X.509 Subject Key Identifiers
val skis = service.information.digitalIdentity.x509SKIs
skis?.forEach { ski ->
println("SKI: ${ski}")
}The module includes built-in validation for required fields:
import eu.europa.ec.eudi.etsi119602.datamodel.Assertions
// Validation is automatic during deserialization
try {
val lote = jsonFormat.decodeFromString<ListOfTrustedEntities>(json)
// If we get here, validation passed
} catch (e: IllegalArgumentException) {
// Validation failed
println("Invalid LoTE: ${e.message}")
}The 119602-data-model module provides the JSON data structures for ETSI TS 119 602 LoTE documents. It is designed to work with the consultation modules:
graph LR
A[LoTE JSON Document] --> B[119602-data-model<br/>Serialization/Deserialization]
B --> C[ListOfTrustedEntities]
C --> D[119602-consultation<br/>Trust Anchor Extraction]
D --> E[consultation<br/>Certificate Validation]
E --> F[Trusted / Not Trusted]
style A fill:#e3f2fd
style B fill:#fff3e0
style C fill:#f3e5f5
style D fill:#fff3e0
style E fill:#c8e6c9
style F fill:#c8e6c9
Typical Usage Flow:
- Deserialize LoTE: Use this module to parse LoTE JSON documents
- Extract Trust Anchors: Use
119602-consultation(when available) to extract certificates - Validate Chains: Use
consultationmodule to validate certificate chains against extracted anchors
- ETSI TS 119 602 - Lists of Trusted Entities (LoTE)
- ETSI TS 119 602 JSON Schema
- Kotlinx Serialization
- EUDI Wallet Reference Implementation
- Root README - Project overview and installation
- Consultation Module - Core abstractions for certificate chain validation
- Consultation-DSS Module - ETSI Trusted Lists support via DSS
Copyright (c) 2026 European Commission
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.