Test plan classes follow this pattern:
[Protocol][Role][CredentialFormat][ClientIdScheme][RequestMethod][ResponseMode]
Examples:
VciWalletSdJwtDpop- VCI Wallet with SD-JWT and DPoPOid4vciIssuerClientAttestationDpop- VCI Issuer with Client Attestation and DPoPSdJwtVcX509SanDnsRequestUriSignedDirectPost- VP Verifier for SD-JWT VC with X.509 client IDVpWalletSdJwtVcX509SanDnsRequestUriSignedDirectPost- VP Wallet for SD-JWT VC with X.509 client ID
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vci/wallet/VciWalletSdJwtDpop.kt
Test Class: VciWalletConformanceTests.kt
Configuration:
- Protocol: OpenID4VCI 1.0
- Role: Wallet (Credential Receiver)
- Credential Format: SD-JWT VC (
vc+sd-jwt) - Authentication: DPoP + private_key_jwt
- Flow: Authorization Code
- Key Binding: openid4vci-proof+jwt
Conformance Plan: oid4vci-1_0-wallet-test-plan
Status: Stable SD-JWT VC reference profile
HAIP Features:
- ✅ DPoP (Demonstrating Proof-of-Possession)
- ✅ private_key_jwt client authentication
- ✅ Key binding proofs (openid4vci-proof+jwt)
- ✅ Nonce handling (c_nonce + nonce_endpoint)
- ✅ Authorization code flow
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vci/wallet/VciWalletSdJwtHaip.kt
Test Class: VciWalletConformanceTests.kt
Configuration:
- Protocol: OpenID4VCI 1.0
- Role: Wallet (Credential Receiver)
- Credential Format: SD-JWT VC (
vc+sd-jwt) - Authentication: DPoP + private_key_jwt
- Flow: Authorization Code
- Profile: HAIP full target (
fapi_profile=vci_haip) - Conformance Plan:
oid4vci-1_0-wallet-haip-test-plan
Purpose: Alternative wallet-side profile aligned to the currently implemented HAIP issuance criteria in OSS. Covers the HAIP-aligned auth-code, DPoP, offer, scope, and SD-JWT validation path without requiring wallet attestation interoperability yet.
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vci/wallet/VciWalletMdocDpop.kt
Test Class: VciWalletConformanceTests.kt
Configuration:
- Protocol: OpenID4VCI 1.0
- Role: Wallet (Credential Receiver)
- Credential Format: ISO mdoc (suite variant
mdoc, issued formatmso_mdoc) - Authentication: DPoP + private_key_jwt
- Flow: Authorization Code
- Conformance Plan:
oid4vci-1_0-wallet-test-plan
Purpose: Wallet-side mdoc issuance profile using the standard VCI wallet test plan with suite variant credential_format=mdoc for issued format mso_mdoc.
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vci/issuer/Oid4vciIssuerClientAttestationDpop.kt
Test Class: IssuerConformanceTests.kt
Configuration:
- Protocol: OpenID4VCI 1.0
- Role: Issuer (Credential Provider)
- Credential Format: SD-JWT VC (
vc+sd-jwt) - Authentication: DPoP + Client Attestation
- Flow: Pre-Authorized Code
- Key Binding: openid4vci-proof+jwt
Test Plan Name: oid4vci-1_0-issuer-test-plan
Current handover variant:
{
"sender_constrain": "dpop",
"client_auth_type": "client_attestation",
"vci_authorization_code_flow_variant": "wallet_initiated",
"credential_format": "sd_jwt_vc",
"authorization_request_type": "simple",
"fapi_request_method": "unsigned",
"vci_grant_type": "pre-authorized_code",
"fapi_profile": "vci",
"fapi_response_mode": "plain_response"
}The conformance-suite UI may display vci_credential_encryption=plain as part of the normalized variant. The runner creates an issuer2 credential offer and adds it to the plan configuration as vci.credential_offer_uri.
Status: Observed passing in the local issuer2 handover setup. Re-run before using as a CI or release gate.
Handover notes:
- Keep the working variant values above unless the changed values are re-tested against the same conformance-suite plan.
- The issuer2 target must trust the attester key via
static-jwkor the generated root CA viax509-chain. - Keycloak is only needed for authorization-code plans, not for this pre-authorized-code issuer baseline.
HAIP Features:
- ✅ DPoP support
- ✅ Client attestation
- ✅ Authorization code flow
- ✅ SD-JWT VC issuance
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vp/verifier/SdJwtVcX509SanDnsRequestUriSignedDirectPost.kt
Test Class: VerifierConformanceTests.kt
Configuration:
- Protocol: OpenID4VP 1.0
- Role: Verifier (Presentation Requestor)
- Credential Format: SD-JWT VC (
dc+sd-jwt) - Client ID Scheme:
x509_san_dns - Request Method:
request_uri_signed(JAR) - Response Mode:
direct_post.jwt(encrypted)
Test Plan Name: oid4vp-1final-verifier-sd-jwt-vc-haip-test-plan
Status:
HAIP Features:
- ✅ X.509 certificate-based client ID
- ✅ Signed authorization requests (JAR)
- ✅ Encrypted response handling
⚠️ Trust anchor configuration needed
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vp/verifier/MdlX509SanDnsRequestUriSignedDirectPost.kt
Test Class: VerifierConformanceTests.kt
Configuration:
- Protocol: OpenID4VP 1.0
- Role: Verifier (Presentation Requestor)
- Credential Format: mDL / ISO 18013-5 (
mso_mdoc) - Client ID Scheme:
x509_san_dns - Request Method:
request_uri_signed(JAR) - Response Mode:
direct_post.jwt(encrypted)
Test Plan Name: oid4vp-1final-verifier-mdl-haip-test-plan
Status: ✅ Tests passing
HAIP Features:
- ✅ X.509 certificate-based client ID
- ✅ Signed authorization requests (JAR)
- ✅ Encrypted response handling
- ✅ mDL (ISO 18013-5) validation
- ✅ DeviceAuth verification
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vp/wallet/VpWalletSdJwtVcX509SanDnsRequestUriSignedDirectPost.kt
Test Class: VpWalletConformanceTests.kt
Configuration:
- Protocol: OpenID4VP 1.0
- Role: Wallet (Presentation Provider)
- Credential Format: SD-JWT VC (
dc+sd-jwt) - Client ID Scheme:
x509_san_dns - Request Method:
request_uri_signed(JAR) - Response Mode:
direct_post.jwt(encrypted)
Test Plan Name: oid4vp-1final-wallet-haip-test-plan
Variant:
{
"credential_format": "sd_jwt_vc",
"response_mode": "direct_post.jwt"
}Status: 🚫 Blocked - Awaiting WAL-896 implementation
Expected Modules (14):
oid4vp-1final-wallet-happy-flowoid4vp-1final-wallet-alternate-request-object-claimsoid4vp-1final-wallet-request-uri-method-postoid4vp-1final-wallet-dcql-sd-jwt-vc-happy-flowoid4vp-1final-wallet-dcql-sd-jwt-vc-credential-queryoid4vp-1final-wallet-dcql-sd-jwt-vc-single-credential-multiple-queriesoid4vp-1final-wallet-ensure-request-object-always-signedoid4vp-1final-wallet-ensure-request-uri-always-presentoid4vp-1final-wallet-ensure-client-id-equals-client-id-schemeoid4vp-1final-wallet-ensure-client-id-x509-san-dnsoid4vp-1final-wallet-ensure-response-type-always-vp-tokenoid4vp-1final-wallet-ensure-response-mode-direct-post-jwtoid4vp-1final-wallet-ensure-response-encryptedoid4vp-1final-wallet-ensure-nonce-always-present
HAIP Features to Test:
- 🚫 Signed request authentication (JAR parsing)
- 🚫 Encrypted response generation (JWE)
- 🚫 KB-JWT holder binding
- 🚫 P-256 key curve enforcement
- 🚫 SHA-256 hash algorithm
- 🚫 X.509 certificate chain validation
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vp/wallet/VpWalletMdlX509SanDnsRequestUriSignedDirectPost.kt
Test Class: VpWalletConformanceTests.kt
Configuration:
- Protocol: OpenID4VP 1.0
- Role: Wallet (Presentation Provider)
- Credential Format: mDL / ISO 18013-5 (
mso_mdoc) - Client ID Scheme:
x509_san_dns - Request Method:
request_uri_signed(JAR) - Response Mode:
direct_post.jwt(encrypted)
Test Plan Name: oid4vp-1final-wallet-haip-test-plan
Variant:
{
"credential_format": "iso_mdl",
"response_mode": "direct_post.jwt"
}Status: 🚫 Blocked - Awaiting WAL-896 implementation
Expected Modules (6):
oid4vp-1final-wallet-mdl-happy-flowoid4vp-1final-wallet-mdl-device-authoid4vp-1final-wallet-mdl-session-transcriptoid4vp-1final-wallet-mdl-invalid-mso-signatureoid4vp-1final-wallet-mdl-invalid-device-signatureoid4vp-1final-wallet-mdl-replay-protection
HAIP Features to Test:
- 🚫 Signed request authentication (JAR parsing)
- 🚫 Encrypted response generation (JWE)
- 🚫 DeviceAuth holder binding
- 🚫 Session transcript validation (ISO 18013-7 Annex C)
- 🚫 X.509 certificate chain validation
File: src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/vp/wallet/VpWalletNegativeTests.kt
Test Class: VpWalletConformanceTests.kt
Configuration:
- Protocol: OpenID4VP 1.0
- Role: Wallet (Presentation Provider)
- Credential Format: SD-JWT VC (
dc+sd-jwt) - Test Type: Negative / Security Validation
Test Plan Name: oid4vp-1final-wallet-haip-test-plan
Variant:
{
"credential_format": "sd_jwt_vc",
"response_mode": "direct_post.jwt"
}Status: 🚫 Blocked - Awaiting WAL-896 implementation
Expected Modules (9):
oid4vp-1final-wallet-reject-unsigned-requestoid4vp-1final-wallet-reject-cleartext-responseoid4vp-1final-wallet-reject-weak-curveoid4vp-1final-wallet-reject-weak-hashoid4vp-1final-wallet-reject-missing-holder-bindingoid4vp-1final-wallet-reject-expired-certificateoid4vp-1final-wallet-reject-untrusted-caoid4vp-1final-wallet-reject-wallet-nonce-mismatchoid4vp-1final-wallet-reject-insecure-origin
HAIP Security Requirements:
- Must reject unsigned requests
- Must reject cleartext response requests
- Must reject weak cryptographic parameters
- Must reject untrusted certificates
- VciWalletSdJwtDpop - stable SD-JWT VC reference profile
- VciWalletMdocDpop - stable ISO mdoc reference profile
- VciWalletSdJwtHaip - HAIP-oriented baseline profile
- Oid4vciIssuerClientAttestationDpop - 53/55 tests passing
- MdlX509SanDnsRequestUriSignedDirectPost - mDL tests passing
- SdJwtVcX509SanDnsRequestUriSignedDirectPost - needs trust anchor config
- VpWalletSdJwtVcX509SanDnsRequestUriSignedDirectPost - awaiting WAL-896
- VpWalletMdlX509SanDnsRequestUriSignedDirectPost - awaiting WAL-896
- VpWalletNegativeTests - awaiting WAL-896
| Interface | Role | Credential Format | Client Auth | Status |
|---|---|---|---|---|
| OpenID4VCI | Wallet | SD-JWT VC | DPoP + private_key_jwt | |
| OpenID4VCI | Wallet | ISO mdoc | DPoP + private_key_jwt | |
| OpenID4VCI | Issuer | SD-JWT VC | DPoP + Client Attestation | |
| OpenID4VP | Verifier | SD-JWT VC | x509_san_dns | |
| OpenID4VP | Verifier | mDL | x509_san_dns | ✅ Passing |
| OpenID4VP | Wallet | SD-JWT VC | x509_san_dns | 🚫 WAL-896 |
| OpenID4VP | Wallet | mDL | x509_san_dns | 🚫 WAL-896 |
| OpenID4VP | Wallet | Negative Tests | x509_san_dns | 🚫 WAL-896 |
All test plans validate HAIP (High Assurance Interoperability Profile) requirements:
- ✅ Signed requests (JAR for VP, DPoP for VCI)
- ✅ Encrypted responses (direct_post.jwt)
- ✅ P-256 key curve
- ✅ SHA-256 hash algorithm
- ✅ Holder binding (KB-JWT or DeviceAuth)
- ✅ DPoP (Demonstrating Proof-of-Possession)
- ✅ private_key_jwt
- ✅ Client Attestation
- ✅ X.509 SAN DNS
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test# VCI Wallet (profile runner)
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test --tests "VciWalletConformanceTests"
# VCI Issuer (mostly passing)
export OPENID4VCI_CONFORMANCE_CREDENTIAL_ISSUER_URL="https://YOUR-NGROK.ngrok-free.app/openid4vc"
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test --tests "IssuerConformanceTests"
# VP Verifier (partial)
export VERIFIER_NGROK_URL="https://YOUR-NGROK.ngrok-free.app"
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test --tests "VerifierConformanceTests"
# VP Wallet (will skip until WAL-896)
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test --tests "VpWalletConformanceTests"# SD-JWT VC VP Wallet
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test \
--tests "VpWalletConformanceTests.VP Wallet - SD-JWT VC*"
# mDL VP Wallet
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test \
--tests "VpWalletConformanceTests.VP Wallet - mDL*"
# Negative Tests
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:test \
--tests "VpWalletConformanceTests.VP Wallet - Negative*"src/main/kotlin/id/walt/openid4vp/conformance/testplans/plans/
├── vci/
│ ├── wallet/
│ │ ├── VciWalletSdJwtDpop.kt ✅
│ │ ├── VciWalletMdocDpop.kt ✅
│ │ └── VciWalletSdJwtHaip.kt ⚠️
│ └── issuer/
│ └── Oid4vciIssuerClientAttestationDpop.kt ⚠️
└── vp/
├── verifier/
│ ├── SdJwtVcX509SanDnsRequestUriSignedDirectPost.kt ⚠️
│ └── MdlX509SanDnsRequestUriSignedDirectPost.kt ✅
└── wallet/
├── VpWalletSdJwtVcX509SanDnsRequestUriSignedDirectPost.kt 🚫
├── VpWalletMdlX509SanDnsRequestUriSignedDirectPost.kt 🚫
└── VpWalletNegativeTests.kt 🚫
src/test/kotlin/id/walt/openid4vp/conformance/
├── VciWalletConformanceTests.kt ⚠️ Profile runner
├── IssuerConformanceTests.kt ⚠️ 53/55
├── VerifierConformanceTests.kt ⚠️ Partial
└── VpWalletConformanceTests.kt 🚫 Ready
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:vciWalletSdJwtVcDpopAuthorizationCode
-PrunIntegrationTests
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:vciWalletIsoMdocDpopAuthorizationCode
-PrunIntegrationTests
./gradlew :waltid-services:waltid-openid4vp-conformance-runners:vciWalletSdJwtVcAuthorizationCodeHaipFullTarget
-PrunIntegrationTests