@learncard/openid4vc-plugin 0.0.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 +21 -0
- package/README.md +592 -0
- package/dist/dcql/adapt.d.ts +80 -0
- package/dist/dcql/adapt.d.ts.map +1 -0
- package/dist/dcql/build.d.ts +122 -0
- package/dist/dcql/build.d.ts.map +1 -0
- package/dist/dcql/compose.d.ts +78 -0
- package/dist/dcql/compose.d.ts.map +1 -0
- package/dist/dcql/index.d.ts +18 -0
- package/dist/dcql/index.d.ts.map +1 -0
- package/dist/dcql/parse.d.ts +16 -0
- package/dist/dcql/parse.d.ts.map +1 -0
- package/dist/dcql/respond.d.ts +115 -0
- package/dist/dcql/respond.d.ts.map +1 -0
- package/dist/dcql/select.d.ts +63 -0
- package/dist/dcql/select.d.ts.map +1 -0
- package/dist/dcql/types.d.ts +93 -0
- package/dist/dcql/types.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/offer/index.d.ts +4 -0
- package/dist/offer/index.d.ts.map +1 -0
- package/dist/offer/normalize.d.ts +15 -0
- package/dist/offer/normalize.d.ts.map +1 -0
- package/dist/offer/parse.d.ts +24 -0
- package/dist/offer/parse.d.ts.map +1 -0
- package/dist/offer/types.d.ts +92 -0
- package/dist/offer/types.d.ts.map +1 -0
- package/dist/openid4vc-plugin.cjs.development.js +27402 -0
- package/dist/openid4vc-plugin.cjs.development.js.map +7 -0
- package/dist/openid4vc-plugin.cjs.production.min.js +146 -0
- package/dist/openid4vc-plugin.cjs.production.min.js.map +7 -0
- package/dist/openid4vc-plugin.esm.js +27396 -0
- package/dist/openid4vc-plugin.esm.js.map +7 -0
- package/dist/plugin.d.ts +12 -0
- package/dist/plugin.d.ts.map +1 -0
- package/dist/siop/index.d.ts +11 -0
- package/dist/siop/index.d.ts.map +1 -0
- package/dist/siop/sign.d.ts +92 -0
- package/dist/siop/sign.d.ts.map +1 -0
- package/dist/types.d.ts +359 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/vci/accept.d.ts +24 -0
- package/dist/vci/accept.d.ts.map +1 -0
- package/dist/vci/auth-code.d.ts +148 -0
- package/dist/vci/auth-code.d.ts.map +1 -0
- package/dist/vci/decode.d.ts +65 -0
- package/dist/vci/decode.d.ts.map +1 -0
- package/dist/vci/errors.d.ts +22 -0
- package/dist/vci/errors.d.ts.map +1 -0
- package/dist/vci/index.d.ts +12 -0
- package/dist/vci/index.d.ts.map +1 -0
- package/dist/vci/metadata.d.ts +25 -0
- package/dist/vci/metadata.d.ts.map +1 -0
- package/dist/vci/pkce.d.ts +85 -0
- package/dist/vci/pkce.d.ts.map +1 -0
- package/dist/vci/proof.d.ts +43 -0
- package/dist/vci/proof.d.ts.map +1 -0
- package/dist/vci/request.d.ts +48 -0
- package/dist/vci/request.d.ts.map +1 -0
- package/dist/vci/store.d.ts +89 -0
- package/dist/vci/store.d.ts.map +1 -0
- package/dist/vci/token.d.ts +16 -0
- package/dist/vci/token.d.ts.map +1 -0
- package/dist/vci/types.d.ts +156 -0
- package/dist/vci/types.d.ts.map +1 -0
- package/dist/vp/client-id-prefix.d.ts +115 -0
- package/dist/vp/client-id-prefix.d.ts.map +1 -0
- package/dist/vp/encrypt.d.ts +221 -0
- package/dist/vp/encrypt.d.ts.map +1 -0
- package/dist/vp/index.d.ts +27 -0
- package/dist/vp/index.d.ts.map +1 -0
- package/dist/vp/parse.d.ts +60 -0
- package/dist/vp/parse.d.ts.map +1 -0
- package/dist/vp/pex.d.ts +83 -0
- package/dist/vp/pex.d.ts.map +1 -0
- package/dist/vp/present.d.ts +126 -0
- package/dist/vp/present.d.ts.map +1 -0
- package/dist/vp/request-object.d.ts +99 -0
- package/dist/vp/request-object.d.ts.map +1 -0
- package/dist/vp/select.d.ts +137 -0
- package/dist/vp/select.d.ts.map +1 -0
- package/dist/vp/sign.d.ts +125 -0
- package/dist/vp/sign.d.ts.map +1 -0
- package/dist/vp/submit.d.ts +175 -0
- package/dist/vp/submit.d.ts.map +1 -0
- package/dist/vp/types.d.ts +255 -0
- package/dist/vp/types.d.ts.map +1 -0
- package/package.json +52 -0
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credential-shape adapter: held credentials → DCQL `DcqlCredential`.
|
|
3
|
+
*
|
|
4
|
+
* The `dcql` library matches credentials via a normalized representation
|
|
5
|
+
* (`DcqlCredential`, a discriminated union over `credential_format`).
|
|
6
|
+
* Our plugin holds credentials in their wire shape — JWT-VC compact
|
|
7
|
+
* strings, JSON-LD VC objects, sometimes a JWT-VC nested inside an
|
|
8
|
+
* LDP envelope's `proof.jwt`. Before DCQL's `query()` matcher can run,
|
|
9
|
+
* we have to translate.
|
|
10
|
+
*
|
|
11
|
+
* # Why this lives in `dcql/` and not in `vp/select.ts`
|
|
12
|
+
*
|
|
13
|
+
* The PEX selector (`vp/select.ts`) decodes credentials internally for
|
|
14
|
+
* its own JSONPath matcher, but its decoded shape (the raw JWT payload
|
|
15
|
+
* verbatim) is not the same as what DCQL wants (a normalized
|
|
16
|
+
* `{ credential_format, type, claims, cryptographic_holder_binding }`).
|
|
17
|
+
* Sharing a single decoder leaks PEX assumptions into DCQL — which is
|
|
18
|
+
* the whole reason DCQL exists as a separate query language. They get
|
|
19
|
+
* separate adapters.
|
|
20
|
+
*
|
|
21
|
+
* # In scope today
|
|
22
|
+
*
|
|
23
|
+
* - `jwt_vc_json` (compact JWT, VCDM §6.3.1 payload).
|
|
24
|
+
* - `ldp_vc` (JSON-LD VC object with a Data Integrity proof or the
|
|
25
|
+
* `proof.type === 'JwtProof2020'` legacy envelope).
|
|
26
|
+
*
|
|
27
|
+
* # Out of scope (deferred)
|
|
28
|
+
*
|
|
29
|
+
* - `vc+sd-jwt` — supported by the `dcql` library but the plugin
|
|
30
|
+
* doesn't yet build SD-JWT *presentations* (KB-JWT signing path
|
|
31
|
+
* is its own slice). Adapter returns `undefined` for these for now
|
|
32
|
+
* so they're transparently skipped during DCQL matching.
|
|
33
|
+
* - `mso_mdoc` — we don't issue or hold mDL credentials yet; the
|
|
34
|
+
* `DcqlMdocCredential` shape requires a CBOR-decoded namespace
|
|
35
|
+
* tree we don't compute.
|
|
36
|
+
*/
|
|
37
|
+
import type { DcqlW3cVcCredential } from './types';
|
|
38
|
+
/** Subset of {@link CandidateCredential} this adapter consumes. */
|
|
39
|
+
export interface AdaptableCredential {
|
|
40
|
+
/** Wire-shape credential — string for JWT-VCs, object for LD-VCs. */
|
|
41
|
+
credential: unknown;
|
|
42
|
+
/**
|
|
43
|
+
* Optional explicit format hint. When omitted the adapter infers
|
|
44
|
+
* via the same heuristics PEX selector uses (`inferCredentialFormat`).
|
|
45
|
+
* Provide explicitly when the wire shape is ambiguous (e.g. a
|
|
46
|
+
* compact JWS that the caller has reason to believe is SD-JWT, not
|
|
47
|
+
* jwt_vc_json).
|
|
48
|
+
*/
|
|
49
|
+
format?: string;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Convert a single held credential into a `DcqlW3cVcCredential` ready
|
|
53
|
+
* for `DcqlQuery.query()` to evaluate.
|
|
54
|
+
*
|
|
55
|
+
* Returns `undefined` when:
|
|
56
|
+
* - format is unrecognized / unsupported (sd-jwt-vc, mdoc, raw JSON
|
|
57
|
+
* without VC shape)
|
|
58
|
+
* - JWT decoding fails (malformed compact JWS, non-JSON payload)
|
|
59
|
+
* - decoded payload has no `vc` claim or `type` array
|
|
60
|
+
*
|
|
61
|
+
* `undefined` results are silently dropped from the candidate pool by
|
|
62
|
+
* downstream selector code — same convention as `vp/select.ts`'s
|
|
63
|
+
* `decodeCandidateForMatching`. Throwing here would force every
|
|
64
|
+
* caller to wrap in try/catch and degrade UX for "I have a weird
|
|
65
|
+
* credential" cases that are otherwise harmless.
|
|
66
|
+
*/
|
|
67
|
+
export declare const adaptCredentialForDcql: (candidate: AdaptableCredential) => DcqlW3cVcCredential | undefined;
|
|
68
|
+
/**
|
|
69
|
+
* Batch adapter — runs {@link adaptCredentialForDcql} over a candidate
|
|
70
|
+
* pool, dropping any that don't normalize. Returns the filtered list
|
|
71
|
+
* pair-wise with the original candidate so callers can reconnect a
|
|
72
|
+
* DCQL match back to the wire-shape credential they actually want to
|
|
73
|
+
* present (the matcher only sees the normalized shape; submission
|
|
74
|
+
* needs the original).
|
|
75
|
+
*/
|
|
76
|
+
export declare const adaptCredentialsForDcql: (candidates: readonly AdaptableCredential[]) => Array<{
|
|
77
|
+
original: AdaptableCredential;
|
|
78
|
+
adapted: DcqlW3cVcCredential;
|
|
79
|
+
}>;
|
|
80
|
+
//# sourceMappingURL=adapt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapt.d.ts","sourceRoot":"","sources":["../../src/dcql/adapt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAEnD,mEAAmE;AACnE,MAAM,WAAW,mBAAmB;IAChC,qEAAqE;IACrE,UAAU,EAAE,OAAO,CAAC;IACpB;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,cACpB,mBAAmB,KAC/B,mBAAmB,GAAG,SAaxB,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,eACpB,SAAS,mBAAmB,EAAE,KAC3C,KAAK,CAAC;IAAE,QAAQ,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE,CASvE,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Build per-credential-query unsigned VPs from a holder's chosen
|
|
3
|
+
* credentials.
|
|
4
|
+
*
|
|
5
|
+
* # Why this exists in addition to `vp/present.ts:buildPresentation`
|
|
6
|
+
*
|
|
7
|
+
* The PEX builder produces ONE VP that wraps every chosen credential
|
|
8
|
+
* (descriptor_map paths thread through it), plus a companion
|
|
9
|
+
* `presentation_submission`. DCQL's response model is fundamentally
|
|
10
|
+
* different per OID4VP 1.0 §6.4:
|
|
11
|
+
*
|
|
12
|
+
* - `vp_token` is an OBJECT keyed by `credential_query_id`.
|
|
13
|
+
* - Each value is its own presentation (one VP per query entry, or
|
|
14
|
+
* an array when the query has `multiple: true`).
|
|
15
|
+
* - There is NO `presentation_submission` field — the keying does
|
|
16
|
+
* the descriptor-map's job implicitly.
|
|
17
|
+
*
|
|
18
|
+
* So this builder takes the same chosen-candidate inputs but returns
|
|
19
|
+
* a per-query collection of `{ credentialQueryId, unsignedVp,
|
|
20
|
+
* vpFormat, candidates }` entries. The signing layer (`./respond.ts`,
|
|
21
|
+
* landing in the next step of this slice) loops over the result and
|
|
22
|
+
* signs each VP individually before assembling the final vp_token
|
|
23
|
+
* object.
|
|
24
|
+
*
|
|
25
|
+
* # Envelope format choice
|
|
26
|
+
*
|
|
27
|
+
* Pure inference from the corresponding query entry's `format`:
|
|
28
|
+
*
|
|
29
|
+
* - `jwt_vc_json` → `jwt_vp_json` envelope
|
|
30
|
+
* - `ldp_vc` → `ldp_vp` envelope
|
|
31
|
+
*
|
|
32
|
+
* No PD-style tie-breaking needed because DCQL queries pin a single
|
|
33
|
+
* format per `credentials[]` entry. SD-JWT and mDoc formats throw
|
|
34
|
+
* — they're tracked for a later slice (different signing pipeline).
|
|
35
|
+
*
|
|
36
|
+
* # Multiple candidates per query
|
|
37
|
+
*
|
|
38
|
+
* DCQL's `multiple: true` lets a single query entry pull more than one
|
|
39
|
+
* credential. We honor this by packing all the candidates with the
|
|
40
|
+
* same `credentialQueryId` into the SAME unsigned VP's
|
|
41
|
+
* `verifiableCredential[]` array — the wallet returns one
|
|
42
|
+
* presentation per query, period. Some verifiers may interpret
|
|
43
|
+
* `multiple: true` as "return an array of presentations", but the
|
|
44
|
+
* spec wording in §6.4 is "an array of one or more presentations" per
|
|
45
|
+
* id, which a single VP carrying multiple VCs satisfies cleanly.
|
|
46
|
+
* Re-visit if a real verifier proves otherwise.
|
|
47
|
+
*/
|
|
48
|
+
import type { UnsignedVP } from '@learncard/types';
|
|
49
|
+
import type { AdaptableCredential } from './adapt';
|
|
50
|
+
import type { DcqlQuery } from './types';
|
|
51
|
+
/** Outer presentation envelope format produced for a DCQL response. */
|
|
52
|
+
export type DcqlVpFormat = 'jwt_vp_json' | 'ldp_vp';
|
|
53
|
+
/**
|
|
54
|
+
* One holder pick: "this candidate satisfies this credential query."
|
|
55
|
+
*
|
|
56
|
+
* Direct analog of `vp/present.ts:ChosenCredential` but keyed by DCQL
|
|
57
|
+
* `credential_query_id` instead of PEX `descriptorId`.
|
|
58
|
+
*/
|
|
59
|
+
export interface DcqlChosenCredential {
|
|
60
|
+
/** Matches `DcqlQuery.credentials[N].id` from the verifier's query. */
|
|
61
|
+
credentialQueryId: string;
|
|
62
|
+
/** Wire-shape credential (JWT-VC string or LD-VC object). */
|
|
63
|
+
candidate: AdaptableCredential;
|
|
64
|
+
}
|
|
65
|
+
export interface BuildDcqlPresentationsInput {
|
|
66
|
+
/**
|
|
67
|
+
* Parsed + validated DCQL query (the one the verifier sent). Used
|
|
68
|
+
* to map `credentialQueryId` → declared format, validate that
|
|
69
|
+
* every chosen entry references a known query id, and to detect
|
|
70
|
+
* `multiple: true`.
|
|
71
|
+
*/
|
|
72
|
+
query: DcqlQuery;
|
|
73
|
+
/** Holder picks. At least one entry per query id MUST be present. */
|
|
74
|
+
chosen: readonly DcqlChosenCredential[];
|
|
75
|
+
/** Holder DID — emitted as `unsignedVp.holder` for VCDM §4.1.1 conformance. */
|
|
76
|
+
holder: string;
|
|
77
|
+
/**
|
|
78
|
+
* Optional presentation id factory — used in tests for
|
|
79
|
+
* deterministic UUIDs. Defaults to a crypto-random hex generator
|
|
80
|
+
* mirroring `vp/present.ts`.
|
|
81
|
+
*/
|
|
82
|
+
makeId?: () => string;
|
|
83
|
+
}
|
|
84
|
+
/** One unsigned VP, ready for the signing layer. */
|
|
85
|
+
export interface BuiltDcqlPresentation {
|
|
86
|
+
/** Matches `DcqlQuery.credentials[N].id`. */
|
|
87
|
+
credentialQueryId: string;
|
|
88
|
+
/** Unsigned VP wrapping the chosen credentials for this query. */
|
|
89
|
+
unsignedVp: UnsignedVP;
|
|
90
|
+
/** Envelope format the signing layer should use. */
|
|
91
|
+
vpFormat: DcqlVpFormat;
|
|
92
|
+
/**
|
|
93
|
+
* Original wire-shape candidates packed into this VP, in the
|
|
94
|
+
* order they appear in `unsignedVp.verifiableCredential`. The
|
|
95
|
+
* submission layer doesn't need this directly, but tests + the
|
|
96
|
+
* future "what was actually presented?" inspection API do.
|
|
97
|
+
*/
|
|
98
|
+
candidates: AdaptableCredential[];
|
|
99
|
+
}
|
|
100
|
+
export type BuildDcqlPresentationErrorCode = 'no_selections' | 'unknown_credential_query' | 'unsupported_format' | 'invalid_jwt_vc';
|
|
101
|
+
export declare class BuildDcqlPresentationError extends Error {
|
|
102
|
+
readonly code: BuildDcqlPresentationErrorCode;
|
|
103
|
+
constructor(code: BuildDcqlPresentationErrorCode, message: string);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Build one unsigned VP per `credential_query_id` referenced in
|
|
107
|
+
* `chosen`. The order of returned entries follows the DCQL query's
|
|
108
|
+
* own `credentials[]` order, so the eventual `vp_token` object's key
|
|
109
|
+
* insertion order matches verifier expectations (most verifiers
|
|
110
|
+
* iterate query entries in declared order when validating).
|
|
111
|
+
*
|
|
112
|
+
* Throws `BuildDcqlPresentationError` on:
|
|
113
|
+
* - empty `chosen`
|
|
114
|
+
* - a chosen entry referencing an id NOT in `query.credentials[]`
|
|
115
|
+
* - a chosen entry whose query format is sd-jwt-vc / mso_mdoc
|
|
116
|
+
* (out-of-scope for this slice; tracked for later)
|
|
117
|
+
* - a `jwt_vc_json` candidate that's neither a compact JWS string
|
|
118
|
+
* nor an object with a string `proof.jwt` (matches the PEX
|
|
119
|
+
* builder's `invalid_jwt_vc` branch)
|
|
120
|
+
*/
|
|
121
|
+
export declare const buildDcqlPresentations: (input: BuildDcqlPresentationsInput) => BuiltDcqlPresentation[];
|
|
122
|
+
//# sourceMappingURL=build.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/dcql/build.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8CG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAMzC,uEAAuE;AACvE,MAAM,MAAM,YAAY,GAAG,aAAa,GAAG,QAAQ,CAAC;AAEpD;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC,uEAAuE;IACvE,iBAAiB,EAAE,MAAM,CAAC;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,mBAAmB,CAAC;CAClC;AAED,MAAM,WAAW,2BAA2B;IACxC;;;;;OAKG;IACH,KAAK,EAAE,SAAS,CAAC;IAEjB,qEAAqE;IACrE,MAAM,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAExC,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC;IAEf;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,MAAM,CAAC;CACzB;AAED,oDAAoD;AACpD,MAAM,WAAW,qBAAqB;IAClC,6CAA6C;IAC7C,iBAAiB,EAAE,MAAM,CAAC;IAC1B,kEAAkE;IAClE,UAAU,EAAE,UAAU,CAAC;IACvB,oDAAoD;IACpD,QAAQ,EAAE,YAAY,CAAC;IACvB;;;;;OAKG;IACH,UAAU,EAAE,mBAAmB,EAAE,CAAC;CACrC;AAMD,MAAM,MAAM,8BAA8B,GACpC,eAAe,GACf,0BAA0B,GAC1B,oBAAoB,GACpB,gBAAgB,CAAC;AAEvB,qBAAa,0BAA2B,SAAQ,KAAK;IACjD,QAAQ,CAAC,IAAI,EAAE,8BAA8B,CAAC;gBAElC,IAAI,EAAE,8BAA8B,EAAE,OAAO,EAAE,MAAM;CAKpE;AAMD;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,sBAAsB,UACxB,2BAA2B,KACnC,qBAAqB,EAwDvB,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import type { DcqlQuery } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Validate + parse a hand-rolled DCQL query input. Lightweight wrapper
|
|
4
|
+
* over {@link parseDcqlQuery} — same throw semantics
|
|
5
|
+
* (`VpError('invalid_dcql_query', ...)` on any structural / content
|
|
6
|
+
* issue), different name to read naturally on the verifier side.
|
|
7
|
+
*/
|
|
8
|
+
export declare const buildDcqlQuery: (input: unknown) => DcqlQuery;
|
|
9
|
+
/**
|
|
10
|
+
* Domain-shaped input for {@link requestW3cVc}. Keeps the common case
|
|
11
|
+
* legible without reaching into the spec-typed schema.
|
|
12
|
+
*/
|
|
13
|
+
export interface RequestW3cVcSpec {
|
|
14
|
+
/**
|
|
15
|
+
* Stable identifier the wallet echoes back as the
|
|
16
|
+
* `credential_query_id` in the response's `vp_token` object.
|
|
17
|
+
* Required and must be unique within a query.
|
|
18
|
+
*/
|
|
19
|
+
id: string;
|
|
20
|
+
/**
|
|
21
|
+
* VC types the credential must declare (in addition to
|
|
22
|
+
* `VerifiableCredential`). Becomes a single AND-clause inside
|
|
23
|
+
* `meta.type_values`. Pass an array of arrays via
|
|
24
|
+
* {@link buildDcqlQuery} directly if you need OR semantics.
|
|
25
|
+
*/
|
|
26
|
+
types: readonly string[];
|
|
27
|
+
/**
|
|
28
|
+
* Wire format. Defaults to `jwt_vc_json` — what walt.id, EUDI, and
|
|
29
|
+
* every learn-card ecosystem issuer emits today.
|
|
30
|
+
*/
|
|
31
|
+
format?: 'jwt_vc_json' | 'ldp_vc';
|
|
32
|
+
/**
|
|
33
|
+
* Optional claim filters. Each entry is a JSON-path-array
|
|
34
|
+
* (`['credentialSubject', 'degreeName']`) and an optional list of
|
|
35
|
+
* acceptable values. The wallet only returns credentials whose
|
|
36
|
+
* actual claim value matches at least one of the listed values
|
|
37
|
+
* (or any value when omitted).
|
|
38
|
+
*/
|
|
39
|
+
claims?: readonly RequestW3cVcClaim[];
|
|
40
|
+
/**
|
|
41
|
+
* Whether the wallet's response MUST carry cryptographic holder
|
|
42
|
+
* binding (i.e. the VP was signed by a key the holder controls).
|
|
43
|
+
* Defaults to `true` — the conservative choice for any flow
|
|
44
|
+
* sensitive to credential theft.
|
|
45
|
+
*/
|
|
46
|
+
requireHolderBinding?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface RequestW3cVcClaim {
|
|
49
|
+
/** JSON path through the credential body, e.g. `['credentialSubject', 'name']`. */
|
|
50
|
+
path: readonly (string | number)[];
|
|
51
|
+
/**
|
|
52
|
+
* Optional list of acceptable values. The wallet may only return
|
|
53
|
+
* credentials whose claim matches at least one entry. Omit for a
|
|
54
|
+
* "must-be-present" filter.
|
|
55
|
+
*/
|
|
56
|
+
values?: readonly (string | number | boolean)[];
|
|
57
|
+
/** Optional id for the claim, used when expressing claim_sets. */
|
|
58
|
+
id?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Build a single-credential DCQL query for a W3C VC. The most common
|
|
62
|
+
* verifier intent collapses to:
|
|
63
|
+
*
|
|
64
|
+
* ```ts
|
|
65
|
+
* const query = requestW3cVc({
|
|
66
|
+
* id: 'degree',
|
|
67
|
+
* types: ['VerifiableCredential', 'UniversityDegree'],
|
|
68
|
+
* claims: [{ path: ['credentialSubject', 'degreeName'] }],
|
|
69
|
+
* });
|
|
70
|
+
* // attach `query` to an Authorization Request as `dcql_query`
|
|
71
|
+
* ```
|
|
72
|
+
*
|
|
73
|
+
* Output is a parsed + validated {@link DcqlQuery} — embed it directly
|
|
74
|
+
* in the Authorization Request URI's `dcql_query` parameter (after
|
|
75
|
+
* `JSON.stringify`+`encodeURIComponent`).
|
|
76
|
+
*/
|
|
77
|
+
export declare const requestW3cVc: (spec: RequestW3cVcSpec) => DcqlQuery;
|
|
78
|
+
//# sourceMappingURL=compose.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../../src/dcql/compose.ts"],"names":[],"mappings":"AAgCA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAMzC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,UAAW,OAAO,KAAG,SAAkC,CAAC;AAEnF;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;;;OAIG;IACH,EAAE,EAAE,MAAM,CAAC;IAEX;;;;;OAKG;IACH,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAEzB;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,GAAG,QAAQ,CAAC;IAElC;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAC;IAEtC;;;;;OAKG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAClC;AAED,MAAM,WAAW,iBAAiB;IAC9B,mFAAmF;IACnF,IAAI,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAEnC;;;;OAIG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,EAAE,CAAC;IAEhD,kEAAkE;IAClE,EAAE,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,YAAY,SAAU,gBAAgB,KAAG,SAsCrD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public DCQL surface — what the plugin exposes to the host LearnCard
|
|
3
|
+
* (and, transitively, to apps consuming `@learncard/openid4vc-plugin`).
|
|
4
|
+
*
|
|
5
|
+
* Holder-side primitives are auto-wired into `presentCredentials` and
|
|
6
|
+
* `prepareVerifiablePresentation` — most app code never imports from
|
|
7
|
+
* here. The export surface exists for advanced callers building their
|
|
8
|
+
* own UI flows or LearnCard apps acting as **verifiers** (in which
|
|
9
|
+
* case `compose` is the entry point).
|
|
10
|
+
*/
|
|
11
|
+
export type { DcqlQuery, DcqlQueryResult, DcqlCredential, DcqlW3cVcCredential, DcqlSdJwtVcCredential, DcqlMdocCredential, DcqlPresentation, DcqlPresentationResult, DcqlPresentationEntry, } from './types';
|
|
12
|
+
export { parseDcqlQuery } from './parse';
|
|
13
|
+
export { adaptCredentialForDcql, adaptCredentialsForDcql, type AdaptableCredential, } from './adapt';
|
|
14
|
+
export { selectCredentialsForDcql, type DcqlSelectionResult, type DcqlCredentialMatch, } from './select';
|
|
15
|
+
export { buildDcqlPresentations, BuildDcqlPresentationError, type BuildDcqlPresentationsInput, type BuiltDcqlPresentation, type DcqlChosenCredential, type DcqlVpFormat, type BuildDcqlPresentationErrorCode, } from './build';
|
|
16
|
+
export { signDcqlPresentations, buildDcqlResponse, assembleDcqlVpToken, type DcqlSignedPresentation, type DcqlInnerVpToken, type DcqlResponse, type SignDcqlPresentationsInput, type SignDcqlPresentationsHelpers, } from './respond';
|
|
17
|
+
export { buildDcqlQuery, requestW3cVc, type RequestW3cVcSpec, type RequestW3cVcClaim, } from './compose';
|
|
18
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dcql/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,YAAY,EACR,SAAS,EACT,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,qBAAqB,GACxB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAEzC,OAAO,EACH,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,mBAAmB,GAC3B,MAAM,SAAS,CAAC;AAEjB,OAAO,EACH,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,GAC3B,MAAM,UAAU,CAAC;AAElB,OAAO,EACH,sBAAsB,EACtB,0BAA0B,EAC1B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,EACzB,KAAK,YAAY,EACjB,KAAK,8BAA8B,GACtC,MAAM,SAAS,CAAC;AAEjB,OAAO,EACH,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,sBAAsB,EAC3B,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,0BAA0B,EAC/B,KAAK,4BAA4B,GACpC,MAAM,WAAW,CAAC;AAGnB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACzB,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DcqlQuery as DcqlQueryType } from './types';
|
|
2
|
+
/**
|
|
3
|
+
* Parse + validate an arbitrary value as a DCQL query. Returns the
|
|
4
|
+
* fully-typed `DcqlQuery` (a.k.a. `DcqlQuery.Output`) ready for
|
|
5
|
+
* `DcqlQuery.query(...)` to consume.
|
|
6
|
+
*
|
|
7
|
+
* Throws `VpError('invalid_dcql_query', ...)` on:
|
|
8
|
+
* - non-object inputs
|
|
9
|
+
* - structural parse errors from `DcqlQuery.parse`
|
|
10
|
+
* - content validation errors from `DcqlQuery.validate`
|
|
11
|
+
*
|
|
12
|
+
* The original `dcql` error is attached as `cause` so debug code can
|
|
13
|
+
* still inspect the precise `valibot` issue tree if needed.
|
|
14
|
+
*/
|
|
15
|
+
export declare const parseDcqlQuery: (raw: unknown) => DcqlQueryType;
|
|
16
|
+
//# sourceMappingURL=parse.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../src/dcql/parse.ts"],"names":[],"mappings":"AAiCA,OAAO,KAAK,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,SAAS,CAAC;AAE1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,cAAc,QAAS,OAAO,KAAG,aAkC7C,CAAC"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sign the per-query unsigned VPs from `./build.ts` and assemble the
|
|
3
|
+
* OID4VP §6.4 DCQL `vp_token` object.
|
|
4
|
+
*
|
|
5
|
+
* # Why this is a separate module from `./build.ts`
|
|
6
|
+
*
|
|
7
|
+
* `./build.ts` is pure / synchronous (just data shaping). Signing
|
|
8
|
+
* touches keys, can be async, and routes through the LearnCard host's
|
|
9
|
+
* crypto plumbing (Ed25519 JWT signer for `jwt_vp_json`,
|
|
10
|
+
* `learnCard.invoke.issuePresentation` for `ldp_vp`). Keeping signing
|
|
11
|
+
* isolated lets tests exercise build without keys, and lets the
|
|
12
|
+
* eventual plugin-level routing call `buildDcqlPresentations →
|
|
13
|
+
* signDcqlPresentations → submitDcqlPresentation` as separate phases.
|
|
14
|
+
*
|
|
15
|
+
* # Wire shape produced
|
|
16
|
+
*
|
|
17
|
+
* Per OID4VP 1.0 §6.4 Wallet response with DCQL:
|
|
18
|
+
*
|
|
19
|
+
* ```jsonc
|
|
20
|
+
* {
|
|
21
|
+
* "vp_token": {
|
|
22
|
+
* "<credentialQueryId>": "<JWT-VP compact JWS>", // jwt_vp_json
|
|
23
|
+
* "<credentialQueryId>": { ...VP json... }, // ldp_vp
|
|
24
|
+
* // ...one entry per `DcqlQuery.credentials[].id` the wallet
|
|
25
|
+
* // chose to fulfill
|
|
26
|
+
* },
|
|
27
|
+
* "state": "<request.state>"
|
|
28
|
+
* // No `presentation_submission` — DCQL keys carry the routing.
|
|
29
|
+
* }
|
|
30
|
+
* ```
|
|
31
|
+
*
|
|
32
|
+
* Submission to `response_uri` happens in the next slice via an
|
|
33
|
+
* extension to `vp/submit.ts` that takes an object-form `vp_token`.
|
|
34
|
+
*/
|
|
35
|
+
import { type LdpVpSigner } from '../vp/sign';
|
|
36
|
+
import type { ProofJwtSigner } from '../vci/types';
|
|
37
|
+
import type { BuiltDcqlPresentation } from './build';
|
|
38
|
+
export interface SignDcqlPresentationsInput {
|
|
39
|
+
/** Output of `buildDcqlPresentations(...)`. */
|
|
40
|
+
built: readonly BuiltDcqlPresentation[];
|
|
41
|
+
/** Audience for every signed VP — typically `request.client_id`. */
|
|
42
|
+
audience: string;
|
|
43
|
+
/** Nonce for every signed VP — `request.nonce` from the auth request. */
|
|
44
|
+
nonce: string;
|
|
45
|
+
/** Holder DID for every VP. */
|
|
46
|
+
holder: string;
|
|
47
|
+
/** Optional fixed `iat` (test determinism). Defaults to `now`. */
|
|
48
|
+
iat?: number;
|
|
49
|
+
}
|
|
50
|
+
export interface SignDcqlPresentationsHelpers {
|
|
51
|
+
/** Required when any `built[].vpFormat === 'jwt_vp_json'`. */
|
|
52
|
+
jwtSigner?: ProofJwtSigner;
|
|
53
|
+
/** Required when any `built[].vpFormat === 'ldp_vp'`. */
|
|
54
|
+
ldpVpSigner?: LdpVpSigner;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* One signed presentation in a DCQL response. The value type is the
|
|
58
|
+
* inner-VP shape (`string` for jwt_vp_json, `VP` for ldp_vp) — not
|
|
59
|
+
* the full {@link VpToken} union, because DCQL responses never nest
|
|
60
|
+
* (you can't have a DCQL object as a value inside another DCQL object).
|
|
61
|
+
*/
|
|
62
|
+
export type DcqlInnerVpToken = string | import('@learncard/types').VP;
|
|
63
|
+
export interface DcqlSignedPresentation {
|
|
64
|
+
credentialQueryId: string;
|
|
65
|
+
vpToken: DcqlInnerVpToken;
|
|
66
|
+
vpFormat: BuiltDcqlPresentation['vpFormat'];
|
|
67
|
+
}
|
|
68
|
+
export interface DcqlResponse {
|
|
69
|
+
/**
|
|
70
|
+
* The OID4VP §6.4 `vp_token` object — keys are `credential_query_id`
|
|
71
|
+
* strings, values are signed presentations. Submission code POSTs
|
|
72
|
+
* this verbatim. Compatible with {@link VpToken}'s
|
|
73
|
+
* `Record<string, string | VP>` arm.
|
|
74
|
+
*/
|
|
75
|
+
vpToken: Record<string, DcqlInnerVpToken>;
|
|
76
|
+
/**
|
|
77
|
+
* Per-query signed-presentation breakdown. Same data as `vpToken`
|
|
78
|
+
* but in array form so callers can iterate / inspect / log
|
|
79
|
+
* without `Object.entries(...)` boilerplate.
|
|
80
|
+
*/
|
|
81
|
+
presentations: DcqlSignedPresentation[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Sign each unsigned VP from {@link buildDcqlPresentations} using the
|
|
85
|
+
* appropriate signer (jwt for jwt_vp_json, ldp for ldp_vp), preserving
|
|
86
|
+
* the per-query `credentialQueryId` association.
|
|
87
|
+
*
|
|
88
|
+
* Throws `VpSignError` (the same code path as PEX signing) on signer
|
|
89
|
+
* misconfiguration; the per-query signing is sequential rather than
|
|
90
|
+
* parallel both because Ed25519 signing is fast (sub-ms per VP) and
|
|
91
|
+
* because some host signers maintain ordered nonce state.
|
|
92
|
+
*/
|
|
93
|
+
export declare const signDcqlPresentations: (input: SignDcqlPresentationsInput, helpers: SignDcqlPresentationsHelpers) => Promise<DcqlSignedPresentation[]>;
|
|
94
|
+
/**
|
|
95
|
+
* Convenience: combine signing + vp_token-object assembly. Use this
|
|
96
|
+
* from plugin-level `presentCredentials` when the route is DCQL;
|
|
97
|
+
* direct callers who want to inspect per-query signing details can
|
|
98
|
+
* call `signDcqlPresentations` and then `assembleDcqlVpToken`
|
|
99
|
+
* themselves.
|
|
100
|
+
*/
|
|
101
|
+
export declare const buildDcqlResponse: (input: SignDcqlPresentationsInput, helpers: SignDcqlPresentationsHelpers) => Promise<DcqlResponse>;
|
|
102
|
+
/**
|
|
103
|
+
* Pure aggregator: per-query signed presentations → vp_token object.
|
|
104
|
+
*
|
|
105
|
+
* Object key order follows the input array order, which the build
|
|
106
|
+
* layer guarantees mirrors the verifier's DCQL `credentials[]`
|
|
107
|
+
* declaration order. Some verifiers iterate query entries in declared
|
|
108
|
+
* order during validation, so this preserves that locality.
|
|
109
|
+
*
|
|
110
|
+
* `multiple: true` queries are not supported in this slice — each
|
|
111
|
+
* query id maps to a single VP. When we add support, the value type
|
|
112
|
+
* widens to `VpToken | VpToken[]`.
|
|
113
|
+
*/
|
|
114
|
+
export declare const assembleDcqlVpToken: (presentations: readonly DcqlSignedPresentation[]) => Record<string, DcqlInnerVpToken>;
|
|
115
|
+
//# sourceMappingURL=respond.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"respond.d.ts","sourceRoot":"","sources":["../../src/dcql/respond.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,OAAO,EAEH,KAAK,WAAW,EACnB,MAAM,YAAY,CAAC;AACpB,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAMrD,MAAM,WAAW,0BAA0B;IACvC,+CAA+C;IAC/C,KAAK,EAAE,SAAS,qBAAqB,EAAE,CAAC;IACxC,oEAAoE;IACpE,QAAQ,EAAE,MAAM,CAAC;IACjB,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;IACd,+BAA+B;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,4BAA4B;IACzC,8DAA8D;IAC9D,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,yDAAyD;IACzD,WAAW,CAAC,EAAE,WAAW,CAAC;CAC7B;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG,OAAO,kBAAkB,EAAE,EAAE,CAAC;AAEtE,MAAM,WAAW,sBAAsB;IACnC,iBAAiB,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,EAAE,qBAAqB,CAAC,UAAU,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,YAAY;IACzB;;;;;OAKG;IACH,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAE1C;;;;OAIG;IACH,aAAa,EAAE,sBAAsB,EAAE,CAAC;CAC3C;AAMD;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,UACvB,0BAA0B,WACxB,4BAA4B,KACtC,OAAO,CAAC,sBAAsB,EAAE,CA8BlC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,UACnB,0BAA0B,WACxB,4BAA4B,KACtC,OAAO,CAAC,YAAY,CAMtB,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,mBAAmB,kBACb,SAAS,sBAAsB,EAAE,KACjD,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAMjC,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { type AdaptableCredential } from './adapt';
|
|
2
|
+
import type { DcqlQueryResult } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Per-credential-query result. Each `DcqlQuery.credentials[]` entry
|
|
5
|
+
* gets exactly one of these in `DcqlSelectionResult.matches[]`,
|
|
6
|
+
* keyed by its `id`.
|
|
7
|
+
*
|
|
8
|
+
* Mirrors `DescriptorSelection` from the PEX selector so UI code can
|
|
9
|
+
* render PEX and DCQL flows identically (a list of "what was asked
|
|
10
|
+
* for" + "which credentials satisfy it" panels).
|
|
11
|
+
*/
|
|
12
|
+
export interface DcqlCredentialMatch {
|
|
13
|
+
/** Matches `DcqlQuery.credentials[N].id` from the verifier's query. */
|
|
14
|
+
credentialQueryId: string;
|
|
15
|
+
/**
|
|
16
|
+
* Wire-shape credentials the matcher accepted for this query
|
|
17
|
+
* entry. Empty when no held credential satisfies the query —
|
|
18
|
+
* see `reason` for the failure summary.
|
|
19
|
+
*/
|
|
20
|
+
candidates: AdaptableCredential[];
|
|
21
|
+
/** Why no candidate matched. Set when `candidates.length === 0`. */
|
|
22
|
+
reason?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Selector result. Mirrors `SelectionResult` (PEX) field-for-field,
|
|
26
|
+
* with `descriptors` renamed to `matches` to reflect DCQL's keying
|
|
27
|
+
* by `credential_query_id`.
|
|
28
|
+
*/
|
|
29
|
+
export interface DcqlSelectionResult {
|
|
30
|
+
/**
|
|
31
|
+
* `true` when the verifier's `credential_sets` (or the implicit
|
|
32
|
+
* "all credentials match" rule when none are declared) can be
|
|
33
|
+
* satisfied by the supplied candidate pool. Drives the "submit"
|
|
34
|
+
* button enablement in UIs.
|
|
35
|
+
*/
|
|
36
|
+
canSatisfy: boolean;
|
|
37
|
+
/** Per-credential-query matches, keyed by `credential_query_id`. */
|
|
38
|
+
matches: Record<string, DcqlCredentialMatch>;
|
|
39
|
+
/** Overall failure reason when `canSatisfy === false`. */
|
|
40
|
+
reason?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Full `dcql` library result. Exposed so advanced callers can
|
|
43
|
+
* drill into trusted-authority validation details, claim-set
|
|
44
|
+
* results, and other DCQL features the simplified plugin shape
|
|
45
|
+
* doesn't surface. Stable as long as `dcql` keeps it stable.
|
|
46
|
+
*/
|
|
47
|
+
raw: DcqlQueryResult;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run the holder's candidate pool against a parsed DCQL query.
|
|
51
|
+
*
|
|
52
|
+
* The supplied `query` MUST already be a `DcqlQuery` (i.e., have
|
|
53
|
+
* passed `DcqlQuery.parse(...) + validate(...)`). The plugin's
|
|
54
|
+
* resolver populates `AuthorizationRequest.dcql_query` exactly that
|
|
55
|
+
* way; callers driving the selector directly should use
|
|
56
|
+
* `parseDcqlQuery` from `./parse.ts` first.
|
|
57
|
+
*
|
|
58
|
+
* Drops candidates whose format the adapter doesn't support
|
|
59
|
+
* (sd-jwt-vc, mso_mdoc — see `./adapt.ts`) without erroring; those
|
|
60
|
+
* simply don't appear in `matches[*].candidates`.
|
|
61
|
+
*/
|
|
62
|
+
export declare const selectCredentialsForDcql: (candidates: readonly AdaptableCredential[], query: import("./types").DcqlQuery) => DcqlSelectionResult;
|
|
63
|
+
//# sourceMappingURL=select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../src/dcql/select.ts"],"names":[],"mappings":"AAiCA,OAAO,EAA2B,KAAK,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAC5E,OAAO,KAAK,EAAa,eAAe,EAAE,MAAM,SAAS,CAAC;AAM1D;;;;;;;;GAQG;AACH,MAAM,WAAW,mBAAmB;IAChC,uEAAuE;IACvE,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;;;OAIG;IACH,UAAU,EAAE,mBAAmB,EAAE,CAAC;IAElC,oEAAoE;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC;;;;;OAKG;IACH,UAAU,EAAE,OAAO,CAAC;IAEpB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,mBAAmB,CAAC,CAAC;IAE7C,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;;;OAKG;IACH,GAAG,EAAE,eAAe,CAAC;CACxB;AAMD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,wBAAwB,eACrB,SAAS,mBAAmB,EAAE,SACnC,OAAO,SAAS,EAAE,SAAS,KACnC,mBAmDF,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plugin-side type bridge to the [`dcql`](https://github.com/openwallet-foundation-labs/dcql-ts)
|
|
3
|
+
* library — Open Wallet Foundation's reference TypeScript implementation
|
|
4
|
+
* of the **Digital Credentials Query Language** (DCQL, OID4VP 1.0 §6).
|
|
5
|
+
*
|
|
6
|
+
* # Why a separate types module
|
|
7
|
+
*
|
|
8
|
+
* `dcql` is the canonical spec-compliant query parser/matcher (authored
|
|
9
|
+
* by Martin Auer, the spec's editor). Re-implementing it would buy us
|
|
10
|
+
* spec drift and nothing else, so the plugin uses it directly. This
|
|
11
|
+
* module exists for two reasons:
|
|
12
|
+
*
|
|
13
|
+
* 1. **Surface curation.** `dcql` exports ~25 type symbols. The
|
|
14
|
+
* plugin only consumes a handful. Re-exporting just those keeps
|
|
15
|
+
* our public API tractable and prevents "leaky transitive types"
|
|
16
|
+
* from creeping into LearnCard's downstream surface.
|
|
17
|
+
*
|
|
18
|
+
* 2. **Plugin-specific ergonomic aliases.** A few `dcql` types want
|
|
19
|
+
* shorter or more domain-specific names when used in the plugin's
|
|
20
|
+
* AuthorizationRequest, selector, and presentation layers.
|
|
21
|
+
*
|
|
22
|
+
* # Coexistence with PEX
|
|
23
|
+
*
|
|
24
|
+
* DCQL is the query language introduced in OID4VP draft 23+ and
|
|
25
|
+
* mandated in OID4VP 1.0. PEX (DIF Presentation Exchange v2, here as
|
|
26
|
+
* `presentation_definition`) is the legacy mechanism used by every
|
|
27
|
+
* pre-1.0 verifier in the wild. The plugin supports BOTH: an incoming
|
|
28
|
+
* AuthorizationRequest may carry either `presentation_definition` or
|
|
29
|
+
* `dcql_query`, and the plugin auto-routes through the corresponding
|
|
30
|
+
* select/build/submit pipeline. See `AuthorizationRequest.dcql_query`
|
|
31
|
+
* (in `../vp/types.ts`) for the discriminator field.
|
|
32
|
+
*
|
|
33
|
+
* # What's in scope
|
|
34
|
+
*
|
|
35
|
+
* The plugin is a **wallet/holder**. Most DCQL surface area is
|
|
36
|
+
* holder-side (parse the verifier's query, match held credentials,
|
|
37
|
+
* emit a DCQL-shaped wallet response). Verifier-side helpers
|
|
38
|
+
* (`buildDcqlQuery`, `validateDcqlPresentation`) are exposed too so
|
|
39
|
+
* LearnCard apps that play the verifier role have ergonomic builders,
|
|
40
|
+
* but the heavy lifting lives in `dcql` itself.
|
|
41
|
+
*/
|
|
42
|
+
import type { DcqlCredential, DcqlMdocCredential, DcqlPresentation, DcqlPresentationResult, DcqlQuery, DcqlQueryResult, DcqlSdJwtVcCredential, DcqlW3cVcCredential } from 'dcql';
|
|
43
|
+
/**
|
|
44
|
+
* The verifier's DCQL query, post-validation. Matches OID4VP 1.0 §6.1.
|
|
45
|
+
*
|
|
46
|
+
* Use `dcql`'s `DcqlQuery.parse(input)` to obtain a value of this type
|
|
47
|
+
* from raw JSON; the plugin's auth-request resolver does that
|
|
48
|
+
* automatically when it sees a `dcql_query` field on an incoming
|
|
49
|
+
* Authorization Request.
|
|
50
|
+
*/
|
|
51
|
+
export type { DcqlQuery, DcqlQueryResult };
|
|
52
|
+
/**
|
|
53
|
+
* Normalized credential shape consumed by `DcqlQuery.query()` (the
|
|
54
|
+
* holder-side matcher). Discriminated by `credential_format`. The
|
|
55
|
+
* adapter at `./adapt.ts` (Slice 2) converts the plugin's wire-format
|
|
56
|
+
* credentials (JWT-VC strings, LD-VC objects, etc.) into this shape.
|
|
57
|
+
*/
|
|
58
|
+
export type { DcqlCredential, DcqlW3cVcCredential, DcqlSdJwtVcCredential, DcqlMdocCredential, };
|
|
59
|
+
/**
|
|
60
|
+
* Wallet's response to a DCQL query — an object keyed by the verifier's
|
|
61
|
+
* `credential_query_id`s, each value being a serialized presentation
|
|
62
|
+
* (JWT-VP for `jwt_vc_json`, compact SD-JWT for `vc+sd-jwt`, etc.).
|
|
63
|
+
*
|
|
64
|
+
* Distinct from PEX's response shape: there's no companion
|
|
65
|
+
* `presentation_submission` because DCQL embeds the routing implicitly
|
|
66
|
+
* in the keying.
|
|
67
|
+
*/
|
|
68
|
+
export type { DcqlPresentation, DcqlPresentationResult };
|
|
69
|
+
/**
|
|
70
|
+
* Single entry in the wallet's DCQL response: a credential-query ID
|
|
71
|
+
* paired with its serialized presentation.
|
|
72
|
+
*
|
|
73
|
+
* Convenience type used by the build/submit layers to keep the per-id
|
|
74
|
+
* loop body legible. The on-the-wire shape is a plain object whose
|
|
75
|
+
* keys are these ids; this type just gives the loop iterator a name.
|
|
76
|
+
*/
|
|
77
|
+
export interface DcqlPresentationEntry {
|
|
78
|
+
/** Matches `credentials[].id` from the verifier's DCQL query. */
|
|
79
|
+
credentialQueryId: string;
|
|
80
|
+
/**
|
|
81
|
+
* Serialized presentation in the format the corresponding query
|
|
82
|
+
* entry asked for:
|
|
83
|
+
* - `jwt_vc_json` → compact JWT-VP string
|
|
84
|
+
* - `ldp_vc` → JSON object (an unsigned VP wrapped with an LD proof)
|
|
85
|
+
* - `vc+sd-jwt` → compact SD-JWT(+KB-JWT) string
|
|
86
|
+
*
|
|
87
|
+
* The plugin currently only emits jwt_vc_json + ldp_vc; sd-jwt-vc
|
|
88
|
+
* presentation is tracked separately (sd-jwt KB-JWT is a different
|
|
89
|
+
* signing path).
|
|
90
|
+
*/
|
|
91
|
+
presentation: string | Record<string, unknown>;
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/dcql/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,KAAK,EACR,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,sBAAsB,EACtB,SAAS,EACT,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACtB,MAAM,MAAM,CAAC;AAMd;;;;;;;GAOG;AACH,YAAY,EAAE,SAAS,EAAE,eAAe,EAAE,CAAC;AAE3C;;;;;GAKG;AACH,YAAY,EACR,cAAc,EACd,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,GACrB,CAAC;AAEF;;;;;;;;GAQG;AACH,YAAY,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,CAAC;AAMzD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IAClC,iEAAiE;IACjE,iBAAiB,EAAE,MAAM,CAAC;IAC1B;;;;;;;;;;OAUG;IACH,YAAY,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClD"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAC9C,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,OAAO,CAAC;AACtB,cAAc,MAAM,CAAC;AACrB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/offer/index.ts"],"names":[],"mappings":"AAAA,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC;AACxB,cAAc,aAAa,CAAC"}
|