dcql 0.4.3-alpha-20250706143223 → 0.5.0-alpha-20250724114402
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.mts +3565 -2482
- package/dist/index.d.ts +3565 -2482
- package/dist/index.js +109 -85
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +109 -85
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
@@ -177,10 +177,19 @@ var v2 = __toESM(require("valibot"));
|
|
177
177
|
// src/u-dcql.ts
|
178
178
|
var v = __toESM(require("valibot"));
|
179
179
|
var idRegex = /^[a-zA-Z0-9_-]+$/;
|
180
|
+
function asNonEmptyArrayOrUndefined(array8) {
|
181
|
+
return array8.length > 0 ? array8 : void 0;
|
182
|
+
}
|
183
|
+
function isNonEmptyArray(array8) {
|
184
|
+
return array8.length > 0;
|
185
|
+
}
|
180
186
|
var vNonEmptyArray = (item) => {
|
181
187
|
return v.pipe(
|
182
|
-
v.array(item),
|
183
|
-
v.custom(
|
188
|
+
v.array(item, (i) => `Expected input to be an array, but received '${i.received}'`),
|
189
|
+
v.custom(
|
190
|
+
(input) => input.length > 0,
|
191
|
+
"Array must be non-empty and have length of at least 1"
|
192
|
+
)
|
184
193
|
);
|
185
194
|
};
|
186
195
|
var vIncludesAll = (subset) => {
|
@@ -255,60 +264,71 @@ var vStringToJson = v.rawTransform(({ dataset, addIssue, NEVER }) => {
|
|
255
264
|
});
|
256
265
|
|
257
266
|
// src/dcql-query/m-dcql-trusted-authorities.ts
|
258
|
-
var getTrustedAuthorityParser = (trustedAuthority) => v2.
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
value: v2.union(
|
265
|
-
trustedAuthority.values.map(
|
266
|
-
(value) => v2.literal(
|
267
|
-
value,
|
268
|
-
(i) => `Expected trusted authority value to be '${value}' but received ${typeof i.input === "string" ? `'${i.input}'` : i.input}`
|
269
|
-
)
|
267
|
+
var getTrustedAuthorityParser = (trustedAuthority) => v2.pipe(
|
268
|
+
v2.object(
|
269
|
+
{
|
270
|
+
type: v2.literal(
|
271
|
+
trustedAuthority.type,
|
272
|
+
(i) => `Expected trusted authority type to be '${trustedAuthority.type}' but received ${typeof i.input === "string" ? `'${i.input}'` : i.input}`
|
270
273
|
),
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
274
|
+
// Some trusted authorities support an array as input type
|
275
|
+
values: v2.pipe(
|
276
|
+
vNonEmptyArray(v2.string()),
|
277
|
+
v2.someItem(
|
278
|
+
(item) => trustedAuthority.values.includes(item),
|
279
|
+
(i) => `Expected one of the trusted authority values to be '${trustedAuthority.values.join("' | '")}' but received '${i.input.join("' , '")}'`
|
280
|
+
)
|
281
|
+
)
|
282
|
+
},
|
283
|
+
`Expected trusted authority object with type '${trustedAuthority.type}' to be defined, but received undefined`
|
284
|
+
),
|
285
|
+
v2.transform(({ values, ...rest }) => ({
|
286
|
+
...rest,
|
287
|
+
value: values.find((value) => trustedAuthority.values.includes(value))
|
288
|
+
}))
|
275
289
|
);
|
276
290
|
var vAuthorityKeyIdentifier = v2.object({
|
277
291
|
type: v2.literal("aki"),
|
278
|
-
|
279
|
-
v2.
|
280
|
-
|
281
|
-
|
282
|
-
|
292
|
+
values: vNonEmptyArray(
|
293
|
+
v2.pipe(
|
294
|
+
v2.string("aki trusted authority value must be a string"),
|
295
|
+
vBase64url,
|
296
|
+
v2.description(
|
297
|
+
"Contains a list of KeyIdentifier entries of the AuthorityKeyIdentifier as defined in Section 4.2.1.1 of [RFC5280], encoded as base64url. The raw byte representation of one of the elements MUST match with the AuthorityKeyIdentifier element of an X.509 certificate in the certificate chain present in the credential (e.g., in the header of an mdoc or SD-JWT). Note that the chain can consist of a single certificate and the credential can include the entire X.509 chain or parts of it."
|
298
|
+
)
|
283
299
|
)
|
284
300
|
)
|
285
301
|
});
|
286
302
|
var vEtsiTrustedList = v2.object({
|
287
303
|
type: v2.literal("etsi_tl"),
|
288
|
-
|
289
|
-
v2.
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
304
|
+
values: vNonEmptyArray(
|
305
|
+
v2.pipe(
|
306
|
+
v2.string("etsi_tl trusted authority value must be a string"),
|
307
|
+
v2.url("etsi_tl trusted authority value must be a valid https url"),
|
308
|
+
v2.check(
|
309
|
+
(url2) => url2.startsWith("http://") || url2.startsWith("https://"),
|
310
|
+
"etsi_tl trusted authority value must be a valid https url"
|
311
|
+
),
|
312
|
+
v2.description(
|
313
|
+
"The identifier of a Trusted List as specified in ETSI TS 119 612 [ETSI.TL]. An ETSI Trusted List contains references to other Trusted Lists, creating a list of trusted lists, or entries for Trust Service Providers with corresponding service description and X.509 Certificates. The trust chain of a matching Credential MUST contain at least one X.509 Certificate that matches one of the entries of the Trusted List or its cascading Trusted Lists."
|
314
|
+
)
|
297
315
|
)
|
298
316
|
)
|
299
317
|
});
|
300
318
|
var vOpenidFederation = v2.object({
|
301
319
|
type: v2.literal("openid_federation"),
|
302
|
-
|
303
|
-
v2.
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
320
|
+
values: vNonEmptyArray(
|
321
|
+
v2.pipe(
|
322
|
+
v2.string("openid_federation trusted authority value must be a string"),
|
323
|
+
v2.url("openid_federation trusted authority value must be a valid https url"),
|
324
|
+
// TODO: should we have a config similar to oid4vc-ts to support http for development?
|
325
|
+
v2.check(
|
326
|
+
(url2) => url2.startsWith("http://") || url2.startsWith("https://"),
|
327
|
+
"openid_federation trusted authority value must be a valid https url"
|
328
|
+
),
|
329
|
+
v2.description(
|
330
|
+
"The Entity Identifier as defined in Section 1 of [OpenID.Federation] that is bound to an entity in a federation. While this Entity Identifier could be any entity in that ecosystem, this entity would usually have the Entity Configuration of a Trust Anchor. A valid trust path, including the given Entity Identifier, must be constructible from a matching credential."
|
331
|
+
)
|
312
332
|
)
|
313
333
|
)
|
314
334
|
});
|
@@ -324,7 +344,7 @@ var DcqlTrustedAuthoritiesQuery;
|
|
324
344
|
)
|
325
345
|
),
|
326
346
|
values: v2.pipe(
|
327
|
-
vNonEmptyArray(authority.entries.
|
347
|
+
vNonEmptyArray(authority.entries.values.item),
|
328
348
|
v2.description(
|
329
349
|
"REQUIRED. An array of strings, where each string (value) contains information specific to the used Trusted Authorities Query type that allows to identify an issuer, trust framework, or a federation that an issuer belongs to."
|
330
350
|
)
|
@@ -710,17 +730,17 @@ var runClaimsQuery = (credentialQuery, ctx) => {
|
|
710
730
|
if (!credentialQuery.claims) {
|
711
731
|
return {
|
712
732
|
success: true,
|
713
|
-
valid_claims:
|
714
|
-
failed_claims:
|
733
|
+
valid_claims: void 0,
|
734
|
+
failed_claims: void 0,
|
715
735
|
valid_claim_sets: [
|
716
736
|
{
|
717
737
|
claim_set_index: void 0,
|
718
738
|
output: {},
|
719
739
|
success: true,
|
720
|
-
valid_claim_indexes:
|
740
|
+
valid_claim_indexes: void 0
|
721
741
|
}
|
722
742
|
],
|
723
|
-
failed_claim_sets:
|
743
|
+
failed_claim_sets: void 0
|
724
744
|
};
|
725
745
|
}
|
726
746
|
const failedClaims = [];
|
@@ -772,7 +792,7 @@ var runClaimsQuery = (credentialQuery, ctx) => {
|
|
772
792
|
success: true,
|
773
793
|
claim_set_index: claimSetIndex,
|
774
794
|
output,
|
775
|
-
valid_claim_indexes: claims.map((claim) => claim.claim_index)
|
795
|
+
valid_claim_indexes: asNonEmptyArrayOrUndefined(claims.map((claim) => claim.claim_index))
|
776
796
|
});
|
777
797
|
} else {
|
778
798
|
const issues = failedClaims.reduce((merged, claim) => deepMerge(claim.issues, merged), {});
|
@@ -781,24 +801,26 @@ var runClaimsQuery = (credentialQuery, ctx) => {
|
|
781
801
|
issues,
|
782
802
|
claim_set_index: claimSetIndex,
|
783
803
|
failed_claim_indexes: claims.filter((claim) => !claim.success).map((claim) => claim.claim_index),
|
784
|
-
valid_claim_indexes:
|
804
|
+
valid_claim_indexes: asNonEmptyArrayOrUndefined(
|
805
|
+
claims.filter((claim) => claim.success).map((claim) => claim.claim_index)
|
806
|
+
)
|
785
807
|
});
|
786
808
|
}
|
787
809
|
}
|
788
|
-
if (validClaimSets
|
810
|
+
if (isNonEmptyArray(validClaimSets)) {
|
789
811
|
return {
|
790
|
-
success:
|
791
|
-
failed_claim_sets: failedClaimSets,
|
792
|
-
|
793
|
-
valid_claims: validClaims.map(({ parser, ...rest }) => rest)
|
812
|
+
success: true,
|
813
|
+
failed_claim_sets: asNonEmptyArrayOrUndefined(failedClaimSets),
|
814
|
+
valid_claim_sets: validClaimSets,
|
815
|
+
valid_claims: asNonEmptyArrayOrUndefined(validClaims.map(({ parser, ...rest }) => rest)),
|
816
|
+
failed_claims: asNonEmptyArrayOrUndefined(failedClaims.map(({ parser, ...rest }) => rest))
|
794
817
|
};
|
795
818
|
}
|
796
819
|
return {
|
797
|
-
success:
|
820
|
+
success: false,
|
798
821
|
failed_claim_sets: failedClaimSets,
|
799
|
-
|
800
|
-
valid_claims: validClaims.map(({ parser, ...rest }) => rest)
|
801
|
-
failed_claims: failedClaims.map(({ parser, ...rest }) => rest)
|
822
|
+
failed_claims: failedClaims.map(({ parser, ...rest }) => rest),
|
823
|
+
valid_claims: asNonEmptyArrayOrUndefined(validClaims.map(({ parser, ...rest }) => rest))
|
802
824
|
};
|
803
825
|
};
|
804
826
|
|
@@ -903,7 +925,7 @@ var runTrustedAuthoritiesQuery = (credentialQuery, credential) => {
|
|
903
925
|
trusted_authority_index: trustedAuthorityIndex,
|
904
926
|
output: parseResult.output
|
905
927
|
},
|
906
|
-
failed_trusted_authorities: failedTrustedAuthorities
|
928
|
+
failed_trusted_authorities: asNonEmptyArrayOrUndefined(failedTrustedAuthorities)
|
907
929
|
};
|
908
930
|
}
|
909
931
|
const issues = v9.flatten(parseResult.issues);
|
@@ -923,12 +945,6 @@ var runTrustedAuthoritiesQuery = (credentialQuery, credential) => {
|
|
923
945
|
// src/dcql-parser/dcql-credential-query-result.ts
|
924
946
|
var runCredentialQuery = (credentialQuery, ctx) => {
|
925
947
|
const { credentials, presentation } = ctx;
|
926
|
-
if (ctx.credentials.length === 0) {
|
927
|
-
throw new DcqlError({
|
928
|
-
message: "Credentials array provided to credential query has length of 0, unable to match credentials against credential query.",
|
929
|
-
code: "BAD_REQUEST"
|
930
|
-
});
|
931
|
-
}
|
932
948
|
const validCredentials = [];
|
933
949
|
const failedCredentials = [];
|
934
950
|
for (const [credentialIndex, credential] of credentials.entries()) {
|
@@ -953,21 +969,20 @@ var runCredentialQuery = (credentialQuery, ctx) => {
|
|
953
969
|
});
|
954
970
|
}
|
955
971
|
}
|
956
|
-
if (
|
972
|
+
if (isNonEmptyArray(validCredentials)) {
|
957
973
|
return {
|
958
|
-
success:
|
974
|
+
success: true,
|
959
975
|
credential_query_id: credentialQuery.id,
|
960
|
-
|
961
|
-
|
962
|
-
valid_credentials: void 0
|
976
|
+
failed_credentials: asNonEmptyArrayOrUndefined(failedCredentials),
|
977
|
+
valid_credentials: validCredentials
|
963
978
|
};
|
964
979
|
}
|
965
980
|
return {
|
966
|
-
success:
|
981
|
+
success: false,
|
967
982
|
credential_query_id: credentialQuery.id,
|
968
|
-
|
969
|
-
|
970
|
-
valid_credentials:
|
983
|
+
// Can be undefined if no credentials were provided to the query
|
984
|
+
failed_credentials: asNonEmptyArrayOrUndefined(failedCredentials),
|
985
|
+
valid_credentials: void 0
|
971
986
|
};
|
972
987
|
};
|
973
988
|
|
@@ -1158,7 +1173,7 @@ var DcqlClaimsResult;
|
|
1158
1173
|
claim_set_index: v12.union([v12.number(), v12.undefined()]),
|
1159
1174
|
// We use indexes because if there are no claim sets, the ids can be undefined
|
1160
1175
|
// Can be empty array in case there are no claims
|
1161
|
-
valid_claim_indexes: v12.
|
1176
|
+
valid_claim_indexes: v12.optional(vNonEmptyArray(v12.number())),
|
1162
1177
|
failed_claim_indexes: v12.optional(v12.undefined()),
|
1163
1178
|
output: vClaimsOutput
|
1164
1179
|
});
|
@@ -1167,20 +1182,20 @@ var DcqlClaimsResult;
|
|
1167
1182
|
// Undefined in case of no claim set
|
1168
1183
|
claim_set_index: v12.union([v12.number(), v12.undefined()]),
|
1169
1184
|
// We use indexes because if there are no claim sets, the ids can be undefined
|
1170
|
-
valid_claim_indexes: v12.
|
1185
|
+
valid_claim_indexes: v12.optional(vNonEmptyArray(v12.number())),
|
1171
1186
|
failed_claim_indexes: vNonEmptyArray(v12.number()),
|
1172
1187
|
issues: v12.record(v12.string(), v12.unknown())
|
1173
1188
|
});
|
1174
1189
|
DcqlClaimsResult2.vClaimsSuccessResult = v12.object({
|
1175
1190
|
success: v12.literal(true),
|
1176
|
-
valid_claims: v12.
|
1177
|
-
failed_claims: v12.
|
1191
|
+
valid_claims: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimsEntrySuccessResult)),
|
1192
|
+
failed_claims: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimsEntryFailureResult)),
|
1178
1193
|
valid_claim_sets: vNonEmptyArray(DcqlClaimsResult2.vClaimSetSuccessResult),
|
1179
|
-
failed_claim_sets: v12.
|
1194
|
+
failed_claim_sets: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimSetFailureResult))
|
1180
1195
|
});
|
1181
1196
|
DcqlClaimsResult2.vClaimsFailureResult = v12.object({
|
1182
1197
|
success: v12.literal(false),
|
1183
|
-
valid_claims: v12.
|
1198
|
+
valid_claims: v12.optional(vNonEmptyArray(DcqlClaimsResult2.vClaimsEntrySuccessResult)),
|
1184
1199
|
failed_claims: vNonEmptyArray(DcqlClaimsResult2.vClaimsEntryFailureResult),
|
1185
1200
|
valid_claim_sets: v12.optional(v12.undefined()),
|
1186
1201
|
failed_claim_sets: vNonEmptyArray(DcqlClaimsResult2.vClaimSetFailureResult)
|
@@ -1215,7 +1230,16 @@ var DcqlTrustedAuthoritiesResult;
|
|
1215
1230
|
DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntrySuccessResult = v14.object({
|
1216
1231
|
success: v14.literal(true),
|
1217
1232
|
trusted_authority_index: v14.number(),
|
1218
|
-
|
1233
|
+
// We map from values (multiple options for a credential/query) to value (the matching option)
|
1234
|
+
output: v14.variant(
|
1235
|
+
"type",
|
1236
|
+
DcqlCredentialTrustedAuthority.vModel.options.map(
|
1237
|
+
(o) => v14.object({
|
1238
|
+
type: o.entries.type,
|
1239
|
+
value: o.entries.values.item
|
1240
|
+
})
|
1241
|
+
)
|
1242
|
+
)
|
1219
1243
|
});
|
1220
1244
|
DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntryFailureResult = v14.object({
|
1221
1245
|
success: v14.literal(false),
|
@@ -1233,7 +1257,7 @@ var DcqlTrustedAuthoritiesResult;
|
|
1233
1257
|
v14.object({
|
1234
1258
|
success: v14.literal(true),
|
1235
1259
|
valid_trusted_authority: DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntrySuccessResult,
|
1236
|
-
failed_trusted_authorities: v14.
|
1260
|
+
failed_trusted_authorities: v14.optional(vNonEmptyArray(DcqlTrustedAuthoritiesResult2.vTrustedAuthorityEntryFailureResult))
|
1237
1261
|
})
|
1238
1262
|
]);
|
1239
1263
|
DcqlTrustedAuthoritiesResult2.vTrustedAuthorityFailureResult = v14.object({
|
@@ -1267,13 +1291,13 @@ var DcqlQueryResult;
|
|
1267
1291
|
success: v15.literal(true),
|
1268
1292
|
credential_query_id: vIdString,
|
1269
1293
|
valid_credentials: vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialSuccessResult),
|
1270
|
-
failed_credentials: v15.
|
1294
|
+
failed_credentials: v15.optional(vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialFailureResult))
|
1271
1295
|
}),
|
1272
1296
|
v15.object({
|
1273
1297
|
success: v15.literal(false),
|
1274
1298
|
credential_query_id: vIdString,
|
1275
1299
|
valid_credentials: v15.optional(v15.undefined()),
|
1276
|
-
failed_credentials: vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialFailureResult)
|
1300
|
+
failed_credentials: v15.optional(vNonEmptyArray(DcqlQueryResult2.vCredentialQueryItemCredentialFailureResult))
|
1277
1301
|
})
|
1278
1302
|
]);
|
1279
1303
|
DcqlQueryResult2.vCredentialQueryResult = v15.record(vIdString, DcqlQueryResult2.vCredentialQueryItemResult);
|
@@ -1349,7 +1373,7 @@ var DcqlPresentationResult;
|
|
1349
1373
|
const dqclQueryMatched = (
|
1350
1374
|
// We require that all the submitted presentations match with the queries
|
1351
1375
|
// So we must have success for all queries, and we don't allow failed_credentials
|
1352
|
-
queriesResults.every((result) => result.success && result.failed_credentials
|
1376
|
+
queriesResults.every((result) => result.success && !result.failed_credentials) && (credentialSetResults ? credentialSetResults.every((set) => !set.required || set.matching_options) : (
|
1353
1377
|
// If not credential_sets are used, we require that at least every credential has a match
|
1354
1378
|
dcqlQuery.credentials.every(
|
1355
1379
|
(credentialQuery) => queriesResults.find((result) => result.credential_query_id === credentialQuery.id)?.success
|