@ewqwe/digital-identity 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,12 @@
1
+ MIT License
2
+ Copyright (c) 2026 NILIMI SAS
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"),
5
+ to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
6
+ and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
9
+
10
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
11
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
12
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # @ewqwe/digital-identity
2
+
3
+ npm-compatible JavaScript/TypeScript library for EU Digital Identity (OpenID4VP, DCQL, mDoc, SD-JWT VC).
4
+
5
+ Part of the [ewQwe TypeScript workspace](../README.md). When used inside the workspace the
6
+ library is resolved via pnpm's `workspace:*` protocol. Published to npm for external consumers.
7
+
8
+ ## Installation
9
+
10
+ ### As an npm dependency (external consumer)
11
+
12
+ ```bash
13
+ npm install @ewqwe/digital-identity
14
+ ```
15
+
16
+ ### Inside the pnpm workspace
17
+
18
+ ```bash
19
+ # From typescript/ root — build the library
20
+ pnpm --filter @ewqwe/digital-identity build
21
+ ```
22
+
23
+ The library is linked into consumers via `workspace:*` in the workspace root.
24
+
25
+ ## Usage
26
+
27
+ ### CommonJS
28
+
29
+ ```javascript
30
+ const { buildAgeVerificationQuery, generateNonce } = require('@ewqwe/digital-identity');
31
+
32
+ const query = buildAgeVerificationQuery(18);
33
+ const nonce = generateNonce();
34
+ ```
35
+
36
+ ### ES Modules
37
+
38
+ ```javascript
39
+ import { buildAgeVerificationQuery, generateNonce } from '@ewqwe/digital-identity';
40
+
41
+ const query = buildAgeVerificationQuery(18);
42
+ const nonce = generateNonce();
43
+ ```
44
+
45
+ ## Features
46
+
47
+ - **DCQL Query Builders**: Build Digital Credentials Query Language queries for OpenID4VP.
48
+ - **Credential Types**: Pre-configured credential types (mDL, PID, Proof of Age, etc.) with associated claims.
49
+ - **Protocol Profiles**: HAIP and Annex A profile support.
50
+ - **Attestation Verification**: JWT signature verification using the Web Crypto API in browsers and Node.js.
51
+ - **Type Definitions**: Full TypeScript support with comprehensive type safety.
52
+
53
+ ## Quick Start
54
+
55
+ ### Generate an age verification query
56
+
57
+ ```javascript
58
+ import { buildAgeVerificationQuery } from '@ewqwe/digital-identity';
59
+
60
+ // Generate query for age 18+
61
+ const query = buildAgeVerificationQuery(18);
62
+ console.log(JSON.stringify(query, null, 2));
63
+
64
+ // Generate query for age 21+
65
+ const query21 = buildAgeVerificationQuery(21);
66
+ ```
67
+
68
+ ### Build an Init Transaction Request
69
+
70
+ ```javascript
71
+ import { buildInitTransactionRequest } from '@ewqwe/digital-identity';
72
+
73
+ const request = buildInitTransactionRequest(
74
+ 'https://example.com',
75
+ 'mdl',
76
+ ['given_name', 'family_name', 'birth_date']
77
+ );
78
+ ```
79
+
80
+ ### Generate a Cryptographic Nonce
81
+
82
+ ```javascript
83
+ import { generateNonce } from '@ewqwe/digital-identity';
84
+
85
+ const nonce = generateNonce();
86
+ // Returns a base64url-encoded 32-byte random value
87
+ ```
88
+
89
+ ### Validate a DCQL Query
90
+
91
+ ```javascript
92
+ import { isValidDCQLQuery, buildAgeVerificationQuery } from '@ewqwe/digital-identity';
93
+
94
+ const query = buildAgeVerificationQuery(18);
95
+ const validation = isValidDCQLQuery(query);
96
+
97
+ if (validation.valid) {
98
+ console.log('Valid DCQL query');
99
+ } else {
100
+ console.error('Invalid:', validation.error);
101
+ }
102
+ ```
103
+
104
+ ## API Reference
105
+
106
+ ### DCQL Query Functions
107
+
108
+ | Function | Description |
109
+ |----------|-------------|
110
+ | `buildAgeVerificationQuery(ageThreshold)` | Build minimal age verification query |
111
+ | `buildAgeVerificationQueryWithFallback(ageThreshold)` | Build query with mDL fallback |
112
+ | `buildInitTransactionRequest(publicUrl, credentialType, claims)` | Build init transaction request |
113
+ | `getDefaultAgeVerificationDCQL()` | Get default age verification query |
114
+ | `determineProfile(credentialType, explicitProfile)` | Determine protocol profile |
115
+ | `generateNonce()` | Generate cryptographic nonce |
116
+ | `isValidDCQLQuery(query)` | Validate DCQL query structure |
117
+ | `parseDCQLQuery(queryString)` | Parse DCQL from JSON string |
118
+ | `extractAgeThreshold(query)` | Extract age threshold from query |
119
+
120
+ ### Credential Types
121
+
122
+ ```javascript
123
+ import { CREDENTIAL_TYPES, getClaimsForType } from '@ewqwe/digital-identity';
124
+
125
+ // Get all credential types
126
+ const types = Object.keys(CREDENTIAL_TYPES);
127
+
128
+ // Get claims for a specific type
129
+ const mdlClaims = getClaimsForType('mdl');
130
+ ```
131
+
132
+ ### Protocol Profiles
133
+
134
+ ```javascript
135
+ import { PROTOCOL_PROFILES, determineProfile } from '@ewqwe/digital-identity';
136
+
137
+ // Get HAIP profile
138
+ const haip = PROTOCOL_PROFILES.haip;
139
+
140
+ // Determine profile for credential type
141
+ const profile = determineProfile('mdl'); // 'haip'
142
+ ```
143
+
144
+ ### Attestation Verification
145
+
146
+ ```javascript
147
+ import { parseAttestation, verifyAttestation } from '@ewqwe/digital-identity';
148
+
149
+ // Parse and verify attestation from backend response
150
+ const attestation = await parseAttestation(jwtToken, '/ewqwe_api/jwks');
151
+
152
+ // Or verify with pre-imported public key
153
+ const publicKey = await importVerifierPublicKey(pemOrSpki);
154
+ const claims = await verifyAttestation(jwtToken, publicKey);
155
+ ```
156
+
157
+ ## API Client
158
+
159
+ `@ewqwe/digital-identity` exports `EwqweApiClient` for server-side and browser client code, with a pluggable `fetch` implementation.
160
+
161
+ ```ts
162
+ import { EwqweApiClient } from '@ewqwe/digital-identity';
163
+
164
+ const apiClient = new EwqweApiClient({
165
+ baseUrl: 'https://localhost:5175',
166
+ fetch: window.fetch,
167
+ });
168
+
169
+ const tx = await apiClient.initOpenID4VPTransaction({
170
+ public_url: 'https://localhost:5174',
171
+ credential_type: 'proof-of-age',
172
+ });
173
+
174
+ const status = await apiClient.getOpenID4VPTransactionStatus(tx.transaction_id);
175
+ const verify = await apiClient.verifyPresentation({
176
+ vp_token: '<vp_token>',
177
+ presentation_submission: null,
178
+ });
179
+ ```
180
+
181
+ ### API client methods
182
+
183
+ - `initOpenID4VPTransaction(request: InitTransactionRequest): Promise<InitTransactionResponse>`
184
+ - `getOpenID4VPTransactionStatus(transactionId: string): Promise<TransactionStatusResult>`
185
+ - `getOpenID4VPAuthorizationRequest(transactionId: string): Promise<OpenID4VPRequest>`
186
+ - `postOpenID4VPAuthorizationRequest(transactionId: string, response: OpenID4VPResponse): Promise<void>`
187
+ - `postOpenID4VPDirectPost(response: OpenID4VPResponse): Promise<void>`
188
+ - `getOpenID4VPJwks(): Promise<{ keys: unknown[] }>`
189
+ - `verifyPresentation(args): Promise<VerifyResponse>`
190
+
191
+ ## License
192
+
193
+ MIT
@@ -0,0 +1,22 @@
1
+ import type { InitTransactionRequest, InitTransactionResponse, OpenID4VPRequest, OpenID4VPResponse, TransactionStatusResult, VerifyRequest, VerifyResponse } from "./types.js";
2
+ export type FetchFn = (input: RequestInfo, init?: RequestInit) => Promise<Response>;
3
+ export interface ApiClientOptions {
4
+ fetch?: FetchFn;
5
+ baseUrl?: string;
6
+ }
7
+ export declare class EwqweApiClient {
8
+ private fetchFn;
9
+ private baseUrl;
10
+ constructor(options?: ApiClientOptions);
11
+ private buildUrl;
12
+ private requestJson;
13
+ initOpenID4VPTransaction(request: InitTransactionRequest): Promise<InitTransactionResponse>;
14
+ getOpenID4VPTransactionStatus(transactionId: string): Promise<TransactionStatusResult>;
15
+ getOpenID4VPAuthorizationRequest(transactionId: string): Promise<OpenID4VPRequest>;
16
+ postOpenID4VPAuthorizationRequest(transactionId: string, authResponse: OpenID4VPResponse): Promise<void>;
17
+ postOpenID4VPDirectPost(response: OpenID4VPResponse): Promise<void>;
18
+ getOpenID4VPJwks(): Promise<{
19
+ keys: unknown[];
20
+ }>;
21
+ verifyPresentation(request: VerifyRequest): Promise<VerifyResponse>;
22
+ }
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Attestation JWT parsing and verification utilities.
3
+ *
4
+ * Browser- and Node-compatible — uses the Web Crypto API only (SubtleCrypto).
5
+ *
6
+ * @module
7
+ */
8
+ /**
9
+ * Decoded payload of a credential verification attestation JWT.
10
+ *
11
+ * Standard JWT claims are typed; all credential-specific claims (e.g.
12
+ * `age_over_18`, `given_name`) are accessible via index signature because they
13
+ * are format-agnostic and defined by the credential schema, not this library.
14
+ */
15
+ export interface Attestation {
16
+ /** Issuer — credential verifier identifier. */
17
+ iss: string;
18
+ /** Subject — transaction / attestation event ID. */
19
+ sub: string;
20
+ /** Audience — relying party identifier (client_id). */
21
+ aud: string;
22
+ /** Expiration time (Unix timestamp seconds). */
23
+ exp: number;
24
+ /** Issued at (Unix timestamp seconds). */
25
+ iat: number;
26
+ /** Not before (Unix timestamp seconds). */
27
+ nbf: number;
28
+ /** Unique attestation ID (UUID). */
29
+ jti: string;
30
+ /** Nonce from the OpenID4VP request (replay prevention). */
31
+ nonce?: string;
32
+ /** Credential doc_type (e.g. `"org.iso.18013.5.1.mDL"`). */
33
+ doc_type?: string;
34
+ /** Credential namespace (e.g. `"org.iso.18013.5.1"`). */
35
+ namespace?: string;
36
+ /** All credential-specific claims, keyed by claim name. */
37
+ [key: string]: unknown;
38
+ }
39
+ /**
40
+ * Base64url-decode a string to a Uint8Array.
41
+ * Handles the standard base64url alphabet (no padding required).
42
+ */
43
+ export declare function base64urlDecode(input: string): Uint8Array;
44
+ /**
45
+ * Import an ES256 (ECDSA P-256) public key for attestation signature verification.
46
+ *
47
+ * Accepts either:
48
+ * - A raw SPKI DER encoded as a base64 string (no headers), or
49
+ * - A PEM-encoded SubjectPublicKeyInfo certificate (`-----BEGIN PUBLIC KEY-----`), or
50
+ * - A PEM-encoded X.509 certificate (`-----BEGIN CERTIFICATE-----`): the Subject
51
+ * Public Key Info is automatically extracted from the TBSCertificate.
52
+ */
53
+ export declare function importVerifierPublicKey(pemOrSpki: string): Promise<CryptoKey>;
54
+ /**
55
+ * Decode and verify an attestation JWT signed by the credential verifier.
56
+ *
57
+ * Steps:
58
+ * 1. Fetches the JWKS from `jwksUrl`.
59
+ * 2. Locates the verification key using the `kid` from the JWT header (falls back
60
+ * to the first key carrying an `x5c` certificate chain).
61
+ * 3. Imports the public key from the DER certificate in `x5c[0]`.
62
+ * 4. Verifies the ES256 signature and checks `exp` / `nbf`.
63
+ * 5. Returns the verified {@link Attestation}.
64
+ *
65
+ * @param jwt - Compact-serialized JWT from `VerifyResponse.attestation`.
66
+ * @param jwksUrl - URL of the JWK Set that contains the attestation signing key,
67
+ * e.g. `"/ewqwe_api/openid4vp/.well-known/jwks.json"`.
68
+ * @throws If the JWKS cannot be fetched, no matching key is found, or verification fails.
69
+ */
70
+ export declare function decodeAttestation(jwt: string): Attestation;
71
+ export declare function getAttestationExpiryStatus(attestation: Attestation): "valid" | "expired" | "not_yet_valid";
72
+ export declare function parseAttestation(jwt: string, jwksUrl: string): Promise<Attestation>;
73
+ /**
74
+ * Verify an ES256 attestation JWT signature and return the decoded claims.
75
+ *
76
+ * @param jwt - The compact-serialized JWT string.
77
+ * @param publicKey - The verifier's public key, obtained from `importVerifierPublicKey`.
78
+ * @throws If the signature is invalid, the JWT is malformed, or the claims are expired.
79
+ */
80
+ export declare function verifyAttestation(jwt: string, publicKey: CryptoKey): Promise<Attestation>;
@@ -0,0 +1,72 @@
1
+ /**
2
+ * @ewqwe/digital-identity — Protocol & Credential Configuration
3
+ *
4
+ * Defines protocol profiles (HAIP, Annex A), credential type specifications
5
+ * (mDL, PID, Proof of Age), and helper functions for querying them.
6
+ *
7
+ * Node.js compatible — no platform-specific APIs.
8
+ *
9
+ * @see https://openid.net/specs/openid-4-verifiable-presentations-1_0.html
10
+ * @see https://ageverification.dev/Technical%20Specification/annexes/annex-A/annex-A-av-profile
11
+ * @see ISO/IEC 18013-5:2021 for mDL claims
12
+ */
13
+ import type { ClaimDefinition, CredentialType, CredentialTypeConfig, ProfileId, ProtocolProfile } from "./types.js";
14
+ /**
15
+ * Protocol Profile Configurations
16
+ *
17
+ * **HAIP (High Assurance Interoperability Profile):**
18
+ * - Used for: mDL, PID (National ID)
19
+ * - Client ID Scheme: x509_hash (X.509 certificate SHA-256 hash)
20
+ * - Request Format: JAR (JWT Authorization Request with x5c header)
21
+ * - Response Mode: direct_post.jwt (encrypted/signed response)
22
+ * - URL Schemes: eudi-openid4vp://, openid4vp://
23
+ * - Reference: OpenID4VP HAIP Draft
24
+ *
25
+ * **Annex A (EU Age Verification Profile):**
26
+ * - Used for: Proof of Age attestations
27
+ * - Client ID Scheme: redirect_uri (redirect URI as client identifier)
28
+ * - Request Format: Plain JSON (redirect_uri scheme forbids signed requests)
29
+ * - Response Mode: direct_post (plain VP token)
30
+ * - URL Schemes: av://
31
+ * - Reference: https://ageverification.dev/Technical%20Specification/annexes/annex-A/annex-A-av-profile
32
+ *
33
+ * Note: The key difference is client_id_scheme. HAIP uses x509_hash with signed JARs,
34
+ * while Annex A uses redirect_uri with plain JSON (signed requests are explicitly forbidden).
35
+ * The `x509_hash` scheme is preferred over `x509_san_dns` because it provides a direct
36
+ * cryptographic binding to the verifier's certificate, independent of DNS resolution.
37
+ */
38
+ export declare const PROTOCOL_PROFILES: Record<ProfileId, ProtocolProfile>;
39
+ /**
40
+ * Credential type configurations based on ISO 18013-5, EU ARF, and EU Age Verification Profile.
41
+ *
42
+ * References:
43
+ * - mDL: ISO/IEC 18013-5:2021
44
+ * - PID: EU ARF Annex 2.02 Topic 3 (PID_04, PID_05)
45
+ * - Proof of Age: EU Age Verification Profile (https://ageverification.dev)
46
+ * - EUDI Wallet document categories: WalletCoreConfig.kt `documentCategories`
47
+ *
48
+ * Credential format identifiers:
49
+ * - `"mso_mdoc"` — ISO/IEC 18013-5 Mobile Documents (CBOR-encoded, namespace-based claims)
50
+ * - `"dc+sd-jwt"` — IETF SD-JWT VC (JSON-encoded, flat or nested claim paths)
51
+ *
52
+ * SD-JWT VC credential types use `vct` (Verifiable Credential Type) as the type
53
+ * identifier instead of `docType`/`namespace`. Claims use JSON paths instead of
54
+ * namespace-based paths. See OpenID4VP 1.0 §B.3 and draft-ietf-oauth-sd-jwt-vc-08.
55
+ */
56
+ export declare const CREDENTIAL_TYPES: Record<CredentialType, CredentialTypeConfig>;
57
+ /**
58
+ * Get default selected claims for a credential type (first 5 claims).
59
+ */
60
+ export declare function getDefaultClaims(credentialType: CredentialType): string[];
61
+ /**
62
+ * Get claim definitions for a credential type.
63
+ */
64
+ export declare function getClaimsForType(credentialType: CredentialType): ClaimDefinition[];
65
+ /**
66
+ * Get the protocol profile for a credential type.
67
+ */
68
+ export declare function getProfileForType(credentialType: CredentialType): ProtocolProfile | null;
69
+ /**
70
+ * Get the profile ID for a credential type.
71
+ */
72
+ export declare function getProfileIdForType(credentialType: CredentialType): ProfileId;
package/dist/dcql.d.ts ADDED
@@ -0,0 +1,266 @@
1
+ /**
2
+ * @ewqwe/digital-identity — DCQL Query Utilities
3
+ *
4
+ * Functions to build, parse, and convert DCQL (Digital Credentials Query Language)
5
+ * queries for EU Age Verification and OpenID4VP presentations.
6
+ *
7
+ * Node.js compatible — uses Node.js crypto API.
8
+ *
9
+ * @see https://openid.net/specs/openid-4-verifiable-presentations-1_0.html §6–7
10
+ * @see https://ageverification.dev/Technical%20Specification/annexes/annex-A/annex-A-av-profile
11
+ */
12
+ import type { CredentialType, InitTransactionRequest, ProfileId } from "./types.js";
13
+ /** EU Age Verification namespace. */
14
+ export declare const EU_AV_NAMESPACE = "eu.europa.ec.av.1";
15
+ /** EU Age Verification mDoc document type. */
16
+ export declare const EU_AV_DOCTYPE = "eu.europa.ec.av.1.mdoc";
17
+ /** ISO 18013-5 mDL namespace. */
18
+ export declare const ISO_MDL_NAMESPACE = "org.iso.18013.5.1";
19
+ /** ISO 18013-5 mDL document type. */
20
+ export declare const ISO_MDL_DOCTYPE = "org.iso.18013.5.1.mDL";
21
+ /** EU PID namespace. */
22
+ export declare const EU_PID_NAMESPACE = "eu.europa.ec.eudi.pid.1";
23
+ /** EU PID document type. */
24
+ export declare const EU_PID_DOCTYPE = "eu.europa.ec.eudi.pid.1";
25
+ /**
26
+ * A single entry in `trusted_authorities` — identifies an authority or trust framework
27
+ * that certifies credential issuers the Verifier will accept.
28
+ *
29
+ * A Credential matches if it satisfies **at least one** entry in the array.
30
+ *
31
+ * Type identifiers defined by OpenID4VP 1.0 §6.1.1:
32
+ * - `"aki"` — X.509 Authority Key Identifier, base64url-encoded (§6.1.1.1)
33
+ * - `"etsi_tl"` — ETSI Trusted List identifier (§6.1.1.2)
34
+ * - `"openid_federation"` — OpenID Federation Entity Identifier (§6.1.1.3)
35
+ *
36
+ * @see https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#section-6.1.1
37
+ */
38
+ export interface TrustedAuthoritiesQuery {
39
+ /** Type identifier for the trust framework. */
40
+ type: "aki" | "etsi_tl" | "openid_federation" | string;
41
+ /** Non-empty array of values interpreted according to `type`. */
42
+ values: string[];
43
+ }
44
+ /** A single claim constraint in a DCQL credential query. */
45
+ export interface DCQLClaimsQuery {
46
+ /** Claim identifier (for referencing in claim_sets). */
47
+ id?: string;
48
+ /**
49
+ * Claims Path Pointer (OpenID4VP 1.0 §7).
50
+ *
51
+ * A **non-empty** array whose elements must be:
52
+ * - `string` — navigate into the named key of an object (§7.1)
53
+ * - `number` (non-negative integer) — select the element at this index in an array (§7.1)
54
+ * - `null` — select **all** elements of the currently selected array(s) (§7.1)
55
+ *
56
+ * For `mso_mdoc` credentials (§7.2) exactly two strings are required:
57
+ * `[namespace, dataElementIdentifier]`.
58
+ *
59
+ * Examples from §7.3:
60
+ * - `["address", "street_address"]` — nested object key
61
+ * - `["degrees", null, "type"]` — all `type` values across the `degrees` array
62
+ * - `["nationalities", 1]` — second element of the `nationalities` array
63
+ */
64
+ path: (string | number | null)[];
65
+ /** Expected values — if provided, claim must match one of these (§6.3). */
66
+ values?: (string | number | boolean)[];
67
+ /** Whether to retain this claim after verification (mso_mdoc only, §B.2.4). */
68
+ intent_to_retain?: boolean;
69
+ }
70
+ /**
71
+ * A single credential query in DCQL.
72
+ *
73
+ * Format identifiers per the OpenID4VP 1.0 spec (Appendix B):
74
+ * - `"mso_mdoc"` — ISO/IEC 18013-5 Mobile Documents (§B.2)
75
+ * - `"dc+sd-jwt"` — IETF SD-JWT VC (§B.3), canonical since Nov 2024
76
+ * (was `"vc+sd-jwt"` before Nov 2024; both SHOULD be accepted per
77
+ * draft-ietf-oauth-sd-jwt-vc-08 §3.2.1)
78
+ * - `"jwt_vc_json"` — W3C VC signed as JWT (§B.1.3.1)
79
+ * - `"ldp_vc"` — W3C VC with Linked Data Proofs (§B.1.3.2)
80
+ *
81
+ * @see https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#appendix-B
82
+ * @see https://www.ietf.org/archive/id/draft-ietf-oauth-sd-jwt-vc-08.html#section-3.2.1
83
+ */
84
+ export interface DCQLCredentialQuery {
85
+ /** Unique identifier for this credential query. */
86
+ id: string;
87
+ /**
88
+ * Credential format identifier.
89
+ *
90
+ * `"mso_mdoc"` is for ISO/IEC 18013-5 Mobile Documents (mDL/mDoc).
91
+ *
92
+ * `"sd-jwt"` formats are for IETF SD-JWT Verifiable Credentials. The current
93
+ * IANA-registered identifier for SD-JWT VC is `"dc+sd-jwt"` (application/dc+sd-jwt),
94
+ * which is the canonical name to use going forward. The older `"vc+sd-jwt"`
95
+ * SHOULD also be accepted during the transitional period per draft-ietf-oauth-sd-jwt-vc-08 §3.2.1.
96
+ *
97
+ * `"jwt_vc_json"` is for W3C Verifiable Credentials signed as JWT without JSON-LD.
98
+ *
99
+ * `"ldp_vc"` is for W3C Verifiable Credentials with Linked Data Proofs.
100
+ */
101
+ format: "mso_mdoc" | "dc+sd-jwt" | "vc+sd-jwt" | "jwt_vc_json" | "ldp_vc";
102
+ /** Format-specific metadata. */
103
+ meta?: {
104
+ /** Document type for mso_mdoc (e.g. "org.iso.18013.5.1.mDL"). */
105
+ doctype_value?: string;
106
+ /** Verifiable Credential Type values for dc+sd-jwt / vc+sd-jwt. */
107
+ vct_values?: string[];
108
+ /** Type values for jwt_vc_json / ldp_vc. */
109
+ type_values?: string[][];
110
+ };
111
+ /** Claims to request from the credential. */
112
+ claims?: DCQLClaimsQuery[];
113
+ /** Named subsets of claims; the wallet picks one set. */
114
+ claim_sets?: string[][];
115
+ /** Allow the wallet to return multiple matching credentials. */
116
+ multiple?: boolean;
117
+ /**
118
+ * Expected authorities or trust frameworks that certify issuers the Verifier will accept.
119
+ *
120
+ * OPTIONAL non-empty array. Every Credential returned by the Wallet SHOULD match at least
121
+ * one of the conditions. The Verifier still bears its own responsibility to verify issuer
122
+ * trust; this field is a hint to the Wallet to avoid sending credentials likely to be
123
+ * rejected. See §6.1.1 for matching semantics per type.
124
+ *
125
+ * @see https://openid.net/specs/openid-4-verifiable-presentations-1_0.html#section-6.1.1
126
+ */
127
+ trusted_authorities?: TrustedAuthoritiesQuery[];
128
+ /**
129
+ * Require cryptographic holder binding in the presentation.
130
+ *
131
+ * OPTIONAL. Default is `true` per §6.1 — a Verifiable Presentation with Cryptographic
132
+ * Holder Binding is required unless explicitly set to `false`.
133
+ */
134
+ require_cryptographic_holder_binding?: boolean;
135
+ }
136
+ /** A credential set defining alternatives (OR logic). */
137
+ export interface DCQLCredentialSetQuery {
138
+ /** Which credential query options satisfy this set. */
139
+ options: string[][];
140
+ /** Whether this credential set is required (default: true). */
141
+ required?: boolean;
142
+ /** Human-readable purpose for this credential set. */
143
+ purpose?: string;
144
+ }
145
+ /** The complete DCQL query structure — OpenID4VP 1.0 §6. */
146
+ export interface DCQLQuery {
147
+ /** Array of credential queries. */
148
+ credentials: DCQLCredentialQuery[];
149
+ /** Optional credential sets for defining alternatives. */
150
+ credential_sets?: DCQLCredentialSetQuery[];
151
+ }
152
+ /**
153
+ * Build a minimal age verification query using the EU AV profile.
154
+ *
155
+ * @param ageThreshold - The age threshold to verify (e.g. 18, 21)
156
+ * @returns DCQL query requesting age_over_N = true
157
+ */
158
+ export declare function buildAgeVerificationQuery(ageThreshold?: number): DCQLQuery;
159
+ /**
160
+ * Build an age verification query with mDL fallback.
161
+ *
162
+ * Uses credential_sets to allow either EU AV proof OR mDL.
163
+ *
164
+ * @param ageThreshold - The age threshold to verify (e.g., 18, 21)
165
+ * @returns DCQL query with EU AV primary and mDL fallback
166
+ */
167
+ export declare function buildAgeVerificationQueryWithFallback(ageThreshold?: number): DCQLQuery;
168
+ /**
169
+ * Default DCQL query requesting age_over_18 from EU PID.
170
+ */
171
+ export declare function getDefaultAgeVerificationDCQL(): DCQLQuery;
172
+ /**
173
+ * Build an `InitTransactionRequest` directly from a credential type and
174
+ * selected claims — the canonical way to initialize an OpenID4VP transaction.
175
+ *
176
+ * Builds a **DCQL query** directly (never a legacy `PresentationDefinition`),
177
+ * so no server-side conversion is required.
178
+ *
179
+ * @param publicUrl - The public URL the wallet is going to call back to
180
+ * @param credentialType - The type of credential to request
181
+ * @param selectedClaims - Array of claim IDs to include (e.g. `["age_over_18"]`)
182
+ * @returns `InitTransactionRequest` ready to POST to `/ewqwe_api/openid4vp/init`
183
+ */
184
+ export declare function buildInitTransactionRequest(publicUrl: string, credentialType: CredentialType, selectedClaims: string[], profile?: ProfileId): InitTransactionRequest;
185
+ /**
186
+ * Determine the protocol profile based on credential type or explicit selection.
187
+ *
188
+ * - mDL and PID → HAIP (x509_san_dns, JAR signing, eudi-openid4vp://)
189
+ * - Proof of Age → Annex A (redirect_uri, plain request, av://)
190
+ */
191
+ export declare function determineProfile(credentialType?: string, explicitProfile?: "haip" | "annex-a"): "haip" | "annex-a";
192
+ /**
193
+ * Generate a cryptographically secure nonce for OpenID4VP requests.
194
+ *
195
+ * @returns Base64URL-encoded random nonce
196
+ */
197
+ export declare function generateNonce(): string;
198
+ /**
199
+ * Validate the structural rules of a DCQL query per OpenID4VP 1.0 §6 and §6.4.1.
200
+ *
201
+ * Rules enforced:
202
+ *
203
+ * **§6 — Top level**
204
+ * - `credentials` MUST be non-empty.
205
+ * - Credential query `id` values MUST be unique across `credentials`.
206
+ * - `credential_sets`, if present, MUST be non-empty.
207
+ * - Each `credential_sets` option element MUST reference a valid credential query `id`.
208
+ *
209
+ * **§6.1 — Credential Query**
210
+ * - Each credential `id` MUST be a non-empty string of alphanumeric, `-`, or `_`.
211
+ * - `trusted_authorities`, if present, MUST be non-empty.
212
+ *
213
+ * **§6.3 & §6.4.1 — Claims / claim_sets**
214
+ * - `claim_sets` MUST NOT be present when `claims` is absent.
215
+ * - Claim `id` values MUST be unique within a single `claims` array.
216
+ * - When `claim_sets` is present, every claim MUST have a non-empty `id`.
217
+ * - Every identifier referenced in `claim_sets` MUST appear in `claims`.
218
+ *
219
+ * @param query - The DCQL query to validate.
220
+ * @returns An object `{ valid: true }` or `{ valid: false, error: string }`.
221
+ */
222
+ export declare function isValidDCQLQuery(query: DCQLQuery): {
223
+ valid: true;
224
+ } | {
225
+ valid: false;
226
+ error: string;
227
+ };
228
+ /**
229
+ * Parse a DCQL query from a string (typically from URL parameters).
230
+ *
231
+ * @param queryString - JSON string containing DCQL query
232
+ * @returns Parsed DCQL query or null if invalid
233
+ */
234
+ export declare function parseDCQLQuery(queryString: string): DCQLQuery | null;
235
+ /**
236
+ * Extract the age threshold from a DCQL query.
237
+ *
238
+ * @param query - DCQL query to analyze
239
+ * @returns Age threshold (e.g. 18, 21) or null if not an age verification query
240
+ */
241
+ export declare function extractAgeThreshold(query: DCQLQuery): number | null;
242
+ /**
243
+ * Build an OpenID4VP authorization request URL for same-device flow.
244
+ */
245
+ export declare function buildAuthorizationRequest(params: {
246
+ rpDomain: string;
247
+ redirectUri: string;
248
+ ageThreshold?: number;
249
+ nonce?: string;
250
+ state?: string;
251
+ }): Record<string, string>;
252
+ /**
253
+ * Build an OpenID4VP authorization request for cross-device flow.
254
+ *
255
+ * Note: When using the HAIP profile with the EUDI Wallet, the client_id should be
256
+ * `x509_hash:<cert_hash>` instead of `x509_san_dns:<domain>` for a direct cryptographic
257
+ * binding to the verifier's certificate. The `x509_san_dns` form is maintained here for
258
+ * legacy compatibility and for deployments that still rely on DNS-based identification.
259
+ */
260
+ export declare function buildCrossDeviceAuthorizationRequest(params: {
261
+ rpDomain: string;
262
+ responseUri: string;
263
+ ageThreshold?: number;
264
+ nonce?: string;
265
+ state?: string;
266
+ }): Record<string, string>;