@openeudi/openid4vp 0.11.1 → 0.12.0

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/dist/index.d.cts CHANGED
@@ -79,10 +79,49 @@ interface HaipQueryInput {
79
79
  claims: string[];
80
80
  trustedAuthorities?: TrustedAuthoritiesQuery[];
81
81
  }
82
+ /**
83
+ * Input to `buildCredentialSetQuery` — a DCQL `credential_sets` disjunction
84
+ * offering the wallet several alternative credentials for the same question.
85
+ */
86
+ interface CredentialSetQueryInput {
87
+ /**
88
+ * The alternatives, **most-preferred first**. Option order is a privacy
89
+ * signal, not cosmetic: list the credential that discloses least first.
90
+ * Wallets are not obliged to honour the order.
91
+ */
92
+ options: HaipQueryInput[];
93
+ /** Whether the wallet must satisfy one option. Default: `true`. */
94
+ required?: boolean;
95
+ }
82
96
 
83
97
  declare const HAIP_DOCTYPE_NAMESPACES: Record<string, string>;
84
98
  declare function buildHaipQuery(input: HaipQueryInput): DcqlQuery;
99
+ /**
100
+ * Build a DCQL query offering the wallet a choice between several credentials —
101
+ * a `credential_sets` disjunction.
102
+ *
103
+ * The motivating case is a proof-of-age check: ask for a Proof-of-Age
104
+ * attestation (`mso_mdoc`, `age_over_18` in namespace `eu.europa.ec.av.1`) OR a
105
+ * PID (`dc+sd-jwt`, `birth_date`), because the PID carries no age attribute and
106
+ * proof-of-age attestations have almost no issuer coverage yet. The wallet
107
+ * satisfies ONE option and returns ONE presentation.
108
+ *
109
+ * This is deliberately NOT HAIP-minimal: `validateHaipQuery` rejects
110
+ * `credential_sets`, and `isHaipQuery` returns `false` for what this produces.
111
+ * That boundary is intentional — use `validateCredentialSetQuery` instead.
112
+ *
113
+ * Each option is built through {@link buildHaipQuery}, so per-credential
114
+ * validation and its `HaipValidationError` codes are identical.
115
+ */
116
+ declare function buildCredentialSetQuery(input: CredentialSetQueryInput): DcqlQuery;
85
117
  declare function validateHaipQuery(query: DcqlQuery): void;
118
+ /**
119
+ * Validate a DCQL query that offers the wallet a choice — the profile
120
+ * `buildCredentialSetQuery` produces. Per-credential rules are identical to
121
+ * HAIP-minimal; the difference is that `credential_sets` is REQUIRED here
122
+ * rather than forbidden.
123
+ */
124
+ declare function validateCredentialSetQuery(query: DcqlQuery): void;
86
125
  declare function isHaipQuery(query: DcqlQuery): boolean;
87
126
 
88
127
  interface IssuerInfo {
@@ -574,7 +613,7 @@ declare class MalformedCredentialError extends Error {
574
613
  declare class NonceValidationError extends Error {
575
614
  constructor(message?: string);
576
615
  }
577
- type HaipValidationCode = 'EMPTY_QUERY' | 'UNSUPPORTED_FORMAT' | 'MISSING_SDJWT_META' | 'MISSING_MDOC_META' | 'NO_CLAIMS' | 'CLAIM_SETS_DISALLOWED' | 'CREDENTIAL_SETS_DISALLOWED';
616
+ type HaipValidationCode = 'EMPTY_QUERY' | 'UNSUPPORTED_FORMAT' | 'MISSING_SDJWT_META' | 'MISSING_MDOC_META' | 'NO_CLAIMS' | 'CLAIM_SETS_DISALLOWED' | 'CREDENTIAL_SETS_DISALLOWED' | 'EMPTY_OPTIONS' | 'DUPLICATE_CREDENTIAL_ID' | 'MISSING_CREDENTIAL_SETS' | 'UNKNOWN_OPTION_REFERENCE';
578
617
  declare class HaipValidationError extends Error {
579
618
  readonly code: HaipValidationCode;
580
619
  readonly credentialId?: string;
@@ -624,6 +663,19 @@ declare class LotlFetchError extends OpenID4VPError {
624
663
  declare class LotlSignatureError extends OpenID4VPError {
625
664
  readonly code: "lotl_signature_invalid";
626
665
  }
666
+ /**
667
+ * The environment is not configured to verify trusted-list signatures at all —
668
+ * distinct from a list whose signature did not verify.
669
+ *
670
+ * `xmldsigjs` needs a WebCrypto engine registered once per process, and this
671
+ * library deliberately leaves that to the consumer rather than picking a
672
+ * provider on their behalf. Without it, no trusted list can ever verify, so
673
+ * this is raised eagerly instead of degrading per-list: a configuration fault
674
+ * reported as a trust failure sends people bisecting valid XML.
675
+ */
676
+ declare class LotlConfigurationError extends OpenID4VPError {
677
+ readonly code: "lotl_configuration_invalid";
678
+ }
627
679
  type SignedRequestBuildErrorCode = 'empty_cert_chain' | 'hostname_cert_mismatch' | 'signing_key_cert_mismatch' | 'missing_encryption_jwk' | 'missing_encryption_alg' | 'missing_vp_formats' | 'unsupported_signing_alg' | 'empty_supported_enc_values' | 'missing_hostname' | 'self_signed_leaf';
628
680
  declare class SignedRequestBuildError extends OpenID4VPError {
629
681
  readonly code: SignedRequestBuildErrorCode;
@@ -693,6 +745,6 @@ declare class LotlTrustStore implements TrustStore {
693
745
  private refresh;
694
746
  }
695
747
 
696
- declare const VERSION = "0.11.1";
748
+ declare const VERSION = "0.12.0";
697
749
 
698
- export { type AuthorizationRequest, type AuthorizationRequestInput, type AuthorizationResponse, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, DecryptionFailedError, type EncryptedResponse, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, type SignedAuthorizationRequest, type SignedAuthorizationRequestInput, SignedRequestBuildError, type SignedRequestBuildErrorCode, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, UnsupportedJweError, VERSION, type VerifyAuthorizationResponseOptions, type VerifyOptions, type VerifyResult, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
750
+ export { type AuthorizationRequest, type AuthorizationRequestInput, type AuthorizationResponse, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, type CredentialSetQueryInput, DecryptionFailedError, type EncryptedResponse, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlConfigurationError, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, type SignedAuthorizationRequest, type SignedAuthorizationRequestInput, SignedRequestBuildError, type SignedRequestBuildErrorCode, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, UnsupportedJweError, VERSION, type VerifyAuthorizationResponseOptions, type VerifyOptions, type VerifyResult, buildCredentialSetQuery, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateCredentialSetQuery, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
package/dist/index.d.ts CHANGED
@@ -79,10 +79,49 @@ interface HaipQueryInput {
79
79
  claims: string[];
80
80
  trustedAuthorities?: TrustedAuthoritiesQuery[];
81
81
  }
82
+ /**
83
+ * Input to `buildCredentialSetQuery` — a DCQL `credential_sets` disjunction
84
+ * offering the wallet several alternative credentials for the same question.
85
+ */
86
+ interface CredentialSetQueryInput {
87
+ /**
88
+ * The alternatives, **most-preferred first**. Option order is a privacy
89
+ * signal, not cosmetic: list the credential that discloses least first.
90
+ * Wallets are not obliged to honour the order.
91
+ */
92
+ options: HaipQueryInput[];
93
+ /** Whether the wallet must satisfy one option. Default: `true`. */
94
+ required?: boolean;
95
+ }
82
96
 
83
97
  declare const HAIP_DOCTYPE_NAMESPACES: Record<string, string>;
84
98
  declare function buildHaipQuery(input: HaipQueryInput): DcqlQuery;
99
+ /**
100
+ * Build a DCQL query offering the wallet a choice between several credentials —
101
+ * a `credential_sets` disjunction.
102
+ *
103
+ * The motivating case is a proof-of-age check: ask for a Proof-of-Age
104
+ * attestation (`mso_mdoc`, `age_over_18` in namespace `eu.europa.ec.av.1`) OR a
105
+ * PID (`dc+sd-jwt`, `birth_date`), because the PID carries no age attribute and
106
+ * proof-of-age attestations have almost no issuer coverage yet. The wallet
107
+ * satisfies ONE option and returns ONE presentation.
108
+ *
109
+ * This is deliberately NOT HAIP-minimal: `validateHaipQuery` rejects
110
+ * `credential_sets`, and `isHaipQuery` returns `false` for what this produces.
111
+ * That boundary is intentional — use `validateCredentialSetQuery` instead.
112
+ *
113
+ * Each option is built through {@link buildHaipQuery}, so per-credential
114
+ * validation and its `HaipValidationError` codes are identical.
115
+ */
116
+ declare function buildCredentialSetQuery(input: CredentialSetQueryInput): DcqlQuery;
85
117
  declare function validateHaipQuery(query: DcqlQuery): void;
118
+ /**
119
+ * Validate a DCQL query that offers the wallet a choice — the profile
120
+ * `buildCredentialSetQuery` produces. Per-credential rules are identical to
121
+ * HAIP-minimal; the difference is that `credential_sets` is REQUIRED here
122
+ * rather than forbidden.
123
+ */
124
+ declare function validateCredentialSetQuery(query: DcqlQuery): void;
86
125
  declare function isHaipQuery(query: DcqlQuery): boolean;
87
126
 
88
127
  interface IssuerInfo {
@@ -574,7 +613,7 @@ declare class MalformedCredentialError extends Error {
574
613
  declare class NonceValidationError extends Error {
575
614
  constructor(message?: string);
576
615
  }
577
- type HaipValidationCode = 'EMPTY_QUERY' | 'UNSUPPORTED_FORMAT' | 'MISSING_SDJWT_META' | 'MISSING_MDOC_META' | 'NO_CLAIMS' | 'CLAIM_SETS_DISALLOWED' | 'CREDENTIAL_SETS_DISALLOWED';
616
+ type HaipValidationCode = 'EMPTY_QUERY' | 'UNSUPPORTED_FORMAT' | 'MISSING_SDJWT_META' | 'MISSING_MDOC_META' | 'NO_CLAIMS' | 'CLAIM_SETS_DISALLOWED' | 'CREDENTIAL_SETS_DISALLOWED' | 'EMPTY_OPTIONS' | 'DUPLICATE_CREDENTIAL_ID' | 'MISSING_CREDENTIAL_SETS' | 'UNKNOWN_OPTION_REFERENCE';
578
617
  declare class HaipValidationError extends Error {
579
618
  readonly code: HaipValidationCode;
580
619
  readonly credentialId?: string;
@@ -624,6 +663,19 @@ declare class LotlFetchError extends OpenID4VPError {
624
663
  declare class LotlSignatureError extends OpenID4VPError {
625
664
  readonly code: "lotl_signature_invalid";
626
665
  }
666
+ /**
667
+ * The environment is not configured to verify trusted-list signatures at all —
668
+ * distinct from a list whose signature did not verify.
669
+ *
670
+ * `xmldsigjs` needs a WebCrypto engine registered once per process, and this
671
+ * library deliberately leaves that to the consumer rather than picking a
672
+ * provider on their behalf. Without it, no trusted list can ever verify, so
673
+ * this is raised eagerly instead of degrading per-list: a configuration fault
674
+ * reported as a trust failure sends people bisecting valid XML.
675
+ */
676
+ declare class LotlConfigurationError extends OpenID4VPError {
677
+ readonly code: "lotl_configuration_invalid";
678
+ }
627
679
  type SignedRequestBuildErrorCode = 'empty_cert_chain' | 'hostname_cert_mismatch' | 'signing_key_cert_mismatch' | 'missing_encryption_jwk' | 'missing_encryption_alg' | 'missing_vp_formats' | 'unsupported_signing_alg' | 'empty_supported_enc_values' | 'missing_hostname' | 'self_signed_leaf';
628
680
  declare class SignedRequestBuildError extends OpenID4VPError {
629
681
  readonly code: SignedRequestBuildErrorCode;
@@ -693,6 +745,6 @@ declare class LotlTrustStore implements TrustStore {
693
745
  private refresh;
694
746
  }
695
747
 
696
- declare const VERSION = "0.11.1";
748
+ declare const VERSION = "0.12.0";
697
749
 
698
- export { type AuthorizationRequest, type AuthorizationRequestInput, type AuthorizationResponse, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, DecryptionFailedError, type EncryptedResponse, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, type SignedAuthorizationRequest, type SignedAuthorizationRequestInput, SignedRequestBuildError, type SignedRequestBuildErrorCode, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, UnsupportedJweError, VERSION, type VerifyAuthorizationResponseOptions, type VerifyOptions, type VerifyResult, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
750
+ export { type AuthorizationRequest, type AuthorizationRequestInput, type AuthorizationResponse, type Cache, CertificateChainError, type ChainErrorReason, CompositeTrustStore, type CredentialClaims, type CredentialFormat, type CredentialSetQueryInput, DecryptionFailedError, type EncryptedResponse, ExpiredCredentialError, type Fetcher, HAIP_DOCTYPE_NAMESPACES, type HaipQueryInput, type HaipValidationCode, HaipValidationError, type ICredentialParser, InMemoryCache, InvalidSignatureError, type IssuerInfo, type LotlAnchorMetadata, LotlConfigurationError, LotlFetchError, LotlSignatureError, LotlTrustStore, type LotlTrustStoreOptions, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, type ParseOptions, type PresentationResult, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, type SignedAuthorizationRequest, type SignedAuthorizationRequestInput, SignedRequestBuildError, type SignedRequestBuildErrorCode, StaticTrustStore, type TrustAnchor, TrustAnchorNotFoundError, type TrustStore, type TrustStoreHint, type TrustStoreInput, UnsupportedFormatError, UnsupportedJweError, VERSION, type VerifyAuthorizationResponseOptions, type VerifyOptions, type VerifyResult, buildCredentialSetQuery, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateCredentialSetQuery, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
package/dist/index.js CHANGED
@@ -24,7 +24,7 @@ var init_reflect_polyfill = __esm({
24
24
  });
25
25
 
26
26
  // src/errors.ts
27
- var InvalidSignatureError, ExpiredCredentialError, UnsupportedFormatError, MalformedCredentialError, NonceValidationError, HaipValidationError, OpenID4VPError, TrustAnchorNotFoundError, CertificateChainError, RevokedCertificateError, RevocationCheckFailedError, LotlFetchError, LotlSignatureError, SignedRequestBuildError, UnsupportedJweError, DecryptionFailedError, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError;
27
+ var InvalidSignatureError, ExpiredCredentialError, UnsupportedFormatError, MalformedCredentialError, NonceValidationError, HaipValidationError, OpenID4VPError, TrustAnchorNotFoundError, CertificateChainError, RevokedCertificateError, RevocationCheckFailedError, LotlFetchError, LotlSignatureError, LotlConfigurationError, SignedRequestBuildError, UnsupportedJweError, DecryptionFailedError, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError;
28
28
  var init_errors = __esm({
29
29
  "src/errors.ts"() {
30
30
  init_reflect_polyfill();
@@ -121,6 +121,9 @@ var init_errors = __esm({
121
121
  LotlSignatureError = class extends OpenID4VPError {
122
122
  code = "lotl_signature_invalid";
123
123
  };
124
+ LotlConfigurationError = class extends OpenID4VPError {
125
+ code = "lotl_configuration_invalid";
126
+ };
124
127
  SignedRequestBuildError = class extends OpenID4VPError {
125
128
  code;
126
129
  constructor(code, message) {
@@ -8422,6 +8425,33 @@ function buildHaipQuery(input) {
8422
8425
  }
8423
8426
  return { credentials: [credential] };
8424
8427
  }
8428
+ function buildCredentialSetQuery(input) {
8429
+ if (input.options.length === 0) {
8430
+ throw new HaipValidationError(
8431
+ "EMPTY_OPTIONS",
8432
+ "a credential set must offer at least one option"
8433
+ );
8434
+ }
8435
+ const seen = /* @__PURE__ */ new Set();
8436
+ for (const option of input.options) {
8437
+ if (seen.has(option.credentialId)) {
8438
+ throw new HaipValidationError(
8439
+ "DUPLICATE_CREDENTIAL_ID",
8440
+ `credential '${option.credentialId}' is declared by more than one option; credential ids must be unique for credential_sets to reference them`,
8441
+ option.credentialId
8442
+ );
8443
+ }
8444
+ seen.add(option.credentialId);
8445
+ }
8446
+ const credentials = input.options.map((option) => buildHaipQuery(option).credentials[0]);
8447
+ const credentialSet = {
8448
+ options: input.options.map((option) => [option.credentialId])
8449
+ };
8450
+ if (input.required === false) {
8451
+ credentialSet.required = false;
8452
+ }
8453
+ return { credentials, credential_sets: [credentialSet] };
8454
+ }
8425
8455
  var HAIP_FORMATS = /* @__PURE__ */ new Set(["dc+sd-jwt", "mso_mdoc"]);
8426
8456
  function validateHaipQuery(query) {
8427
8457
  if (!query.credentials || query.credentials.length === 0) {
@@ -8437,46 +8467,86 @@ function validateHaipQuery(query) {
8437
8467
  );
8438
8468
  }
8439
8469
  for (const credential of query.credentials) {
8440
- if (!HAIP_FORMATS.has(credential.format)) {
8470
+ validateCredential(credential);
8471
+ }
8472
+ }
8473
+ function validateCredential(credential) {
8474
+ if (!HAIP_FORMATS.has(credential.format)) {
8475
+ throw new HaipValidationError(
8476
+ "UNSUPPORTED_FORMAT",
8477
+ `credential '${credential.id}' uses unsupported format '${credential.format}' (allowed: dc+sd-jwt, mso_mdoc)`,
8478
+ credential.id
8479
+ );
8480
+ }
8481
+ if (credential.format === "dc+sd-jwt") {
8482
+ const vctValues = credential.meta?.vct_values;
8483
+ if (!vctValues || vctValues.length === 0) {
8441
8484
  throw new HaipValidationError(
8442
- "UNSUPPORTED_FORMAT",
8443
- `credential '${credential.id}' uses unsupported format '${credential.format}' (allowed: dc+sd-jwt, mso_mdoc)`,
8485
+ "MISSING_SDJWT_META",
8486
+ `credential '${credential.id}' with format 'dc+sd-jwt' must set meta.vct_values`,
8444
8487
  credential.id
8445
8488
  );
8446
8489
  }
8447
- if (credential.format === "dc+sd-jwt") {
8448
- const vctValues = credential.meta?.vct_values;
8449
- if (!vctValues || vctValues.length === 0) {
8450
- throw new HaipValidationError(
8451
- "MISSING_SDJWT_META",
8452
- `credential '${credential.id}' with format 'dc+sd-jwt' must set meta.vct_values`,
8453
- credential.id
8454
- );
8455
- }
8456
- }
8457
- if (credential.format === "mso_mdoc") {
8458
- if (typeof credential.meta?.doctype_value !== "string") {
8459
- throw new HaipValidationError(
8460
- "MISSING_MDOC_META",
8461
- `credential '${credential.id}' with format 'mso_mdoc' must set meta.doctype_value`,
8462
- credential.id
8463
- );
8464
- }
8465
- }
8466
- if (!credential.claims || credential.claims.length === 0) {
8490
+ }
8491
+ if (credential.format === "mso_mdoc") {
8492
+ if (typeof credential.meta?.doctype_value !== "string") {
8467
8493
  throw new HaipValidationError(
8468
- "NO_CLAIMS",
8469
- `credential '${credential.id}' must declare at least one claim`,
8494
+ "MISSING_MDOC_META",
8495
+ `credential '${credential.id}' with format 'mso_mdoc' must set meta.doctype_value`,
8470
8496
  credential.id
8471
8497
  );
8472
8498
  }
8473
- if (credential.claim_sets !== void 0) {
8499
+ }
8500
+ if (!credential.claims || credential.claims.length === 0) {
8501
+ throw new HaipValidationError(
8502
+ "NO_CLAIMS",
8503
+ `credential '${credential.id}' must declare at least one claim`,
8504
+ credential.id
8505
+ );
8506
+ }
8507
+ if (credential.claim_sets !== void 0) {
8508
+ throw new HaipValidationError(
8509
+ "CLAIM_SETS_DISALLOWED",
8510
+ `credential '${credential.id}' uses claim_sets, not permitted in HAIP-minimal`,
8511
+ credential.id
8512
+ );
8513
+ }
8514
+ }
8515
+ function validateCredentialSetQuery(query) {
8516
+ if (!query.credentials || query.credentials.length === 0) {
8517
+ throw new HaipValidationError(
8518
+ "EMPTY_QUERY",
8519
+ "query.credentials must have at least one entry"
8520
+ );
8521
+ }
8522
+ if (!query.credential_sets || query.credential_sets.length === 0) {
8523
+ throw new HaipValidationError(
8524
+ "MISSING_CREDENTIAL_SETS",
8525
+ "a credential-set query must declare at least one credential_sets entry"
8526
+ );
8527
+ }
8528
+ for (const credential of query.credentials) {
8529
+ validateCredential(credential);
8530
+ }
8531
+ const declaredIds = new Set(query.credentials.map((c) => c.id));
8532
+ for (const credentialSet of query.credential_sets) {
8533
+ if (!credentialSet.options || credentialSet.options.length === 0) {
8474
8534
  throw new HaipValidationError(
8475
- "CLAIM_SETS_DISALLOWED",
8476
- `credential '${credential.id}' uses claim_sets, not permitted in HAIP-minimal`,
8477
- credential.id
8535
+ "EMPTY_OPTIONS",
8536
+ "a credential set must offer at least one option"
8478
8537
  );
8479
8538
  }
8539
+ for (const option of credentialSet.options) {
8540
+ for (const id of option) {
8541
+ if (!declaredIds.has(id)) {
8542
+ throw new HaipValidationError(
8543
+ "UNKNOWN_OPTION_REFERENCE",
8544
+ `credential_sets option references '${id}', which is not declared in query.credentials`,
8545
+ id
8546
+ );
8547
+ }
8548
+ }
8549
+ }
8480
8550
  }
8481
8551
  }
8482
8552
  function isHaipQuery(query) {
@@ -9946,6 +10016,7 @@ function bytesToHex3(bytes) {
9946
10016
 
9947
10017
  // src/trust/LotlTrustStore.ts
9948
10018
  init_reflect_polyfill();
10019
+ init_errors();
9949
10020
 
9950
10021
  // src/trust/lotl-signing-anchors.ts
9951
10022
  init_reflect_polyfill();
@@ -10014,6 +10085,7 @@ var LotlFetcher = class {
10014
10085
  this.fetcher = opts.fetcher ?? globalThis.fetch.bind(globalThis);
10015
10086
  }
10016
10087
  async fetchSigned(url, signingAnchors) {
10088
+ assertCryptoEngineRegistered();
10017
10089
  let xmlText;
10018
10090
  try {
10019
10091
  const response = await this.fetcher(url, { method: "GET" });
@@ -10066,6 +10138,22 @@ var LotlFetcher = class {
10066
10138
  );
10067
10139
  }
10068
10140
  };
10141
+ function assertCryptoEngineRegistered() {
10142
+ let engine;
10143
+ try {
10144
+ engine = xmldsig.Application.crypto;
10145
+ } catch (err) {
10146
+ throw new LotlConfigurationError(
10147
+ `no xmldsigjs crypto engine registered \u2014 trusted-list signatures cannot be verified. Call xmldsig.Application.setEngine('NodeJS', new Crypto()) (e.g. from @peculiar/webcrypto) once at startup, before using LotlTrustStore. Underlying error: ${err instanceof Error ? err.message : String(err)}`,
10148
+ { cause: err instanceof Error ? err : void 0 }
10149
+ );
10150
+ }
10151
+ if (!engine) {
10152
+ throw new LotlConfigurationError(
10153
+ "no xmldsigjs crypto engine registered \u2014 trusted-list signatures cannot be verified. Call xmldsig.Application.setEngine('NodeJS', new Crypto()) (e.g. from @peculiar/webcrypto) once at startup, before using LotlTrustStore."
10154
+ );
10155
+ }
10156
+ }
10069
10157
  async function verifyAgainst(doc, sigEl, anchor) {
10070
10158
  try {
10071
10159
  const signed = new xmldsig.SignedXml(doc);
@@ -10213,6 +10301,7 @@ function parsePointer(el) {
10213
10301
 
10214
10302
  // src/trust/NationalTlResolver.ts
10215
10303
  init_reflect_polyfill();
10304
+ init_errors();
10216
10305
  var TSL_NS2 = "http://uri.etsi.org/02231/v2#";
10217
10306
  var NationalTlResolver = class {
10218
10307
  constructor(opts) {
@@ -10228,6 +10317,7 @@ var NationalTlResolver = class {
10228
10317
  );
10229
10318
  return parseNationalTl(doc, pointer.country);
10230
10319
  } catch (err) {
10320
+ if (err instanceof LotlConfigurationError) throw err;
10231
10321
  console.warn(
10232
10322
  `[openid4vp] national TL for ${pointer.country} failed: ${err.message}`
10233
10323
  );
@@ -10406,6 +10496,7 @@ var LotlTrustStore = class {
10406
10496
  };
10407
10497
  return this.snapshot;
10408
10498
  } catch (err) {
10499
+ if (err instanceof LotlConfigurationError) throw err;
10409
10500
  if (this.snapshot) {
10410
10501
  console.warn(
10411
10502
  `[openid4vp] LOTL refresh failed; serving cached snapshot (${err.message})`
@@ -10453,7 +10544,7 @@ function equalBytes(a, b) {
10453
10544
 
10454
10545
  // src/index.ts
10455
10546
  init_errors();
10456
- var VERSION = "0.11.1";
10547
+ var VERSION = "0.12.0";
10457
10548
  /*! Bundled license information:
10458
10549
 
10459
10550
  pvtsutils/build/index.es.js:
@@ -10523,6 +10614,6 @@ asn1js/build/index.es.js:
10523
10614
  *)
10524
10615
  */
10525
10616
 
10526
- export { CertificateChainError, CompositeTrustStore, DecryptionFailedError, ExpiredCredentialError, HAIP_DOCTYPE_NAMESPACES, HaipValidationError, InMemoryCache, InvalidSignatureError, LotlFetchError, LotlSignatureError, LotlTrustStore, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, SignedRequestBuildError, StaticTrustStore, TrustAnchorNotFoundError, UnsupportedFormatError, UnsupportedJweError, VERSION, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
10617
+ export { CertificateChainError, CompositeTrustStore, DecryptionFailedError, ExpiredCredentialError, HAIP_DOCTYPE_NAMESPACES, HaipValidationError, InMemoryCache, InvalidSignatureError, LotlConfigurationError, LotlFetchError, LotlSignatureError, LotlTrustStore, MalformedCredentialError, MdocParser, MissingDecryptionKeyError, MissingVerifierEncryptionKeyError, MultipleCredentialsNotSupportedError, NonceValidationError, OpenID4VPError, RevocationCheckFailedError, RevokedCertificateError, SdJwtParser, SignedRequestBuildError, StaticTrustStore, TrustAnchorNotFoundError, UnsupportedFormatError, UnsupportedJweError, VERSION, buildCredentialSetQuery, buildHaipQuery, buildOid4vpSessionTranscript, buildOpenID4VPHandoverSessionTranscript, createAuthorizationRequest, createSignedAuthorizationRequest, decryptAuthorizationResponse, isHaipQuery, parsePresentation, validateCredentialSetQuery, validateHaipQuery, verifyAuthorizationResponse, verifyPresentation };
10527
10618
  //# sourceMappingURL=index.js.map
10528
10619
  //# sourceMappingURL=index.js.map