@ixo/credentials-kit 0.0.0-stage → 0.1.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.
Files changed (72) hide show
  1. package/README.md +469 -2
  2. package/dist/chunk-2SF56NEJ.js +1053 -0
  3. package/dist/chunk-2SF56NEJ.js.map +1 -0
  4. package/dist/chunk-46VRPQPD.js +176 -0
  5. package/dist/chunk-46VRPQPD.js.map +1 -0
  6. package/dist/chunk-AQ3IINHC.js +138 -0
  7. package/dist/chunk-AQ3IINHC.js.map +1 -0
  8. package/dist/chunk-FSKCDHZ7.js +613 -0
  9. package/dist/chunk-FSKCDHZ7.js.map +1 -0
  10. package/dist/chunk-I6GBYFIJ.js +89 -0
  11. package/dist/chunk-I6GBYFIJ.js.map +1 -0
  12. package/dist/chunk-JBUX6V2Q.js +210 -0
  13. package/dist/chunk-JBUX6V2Q.js.map +1 -0
  14. package/dist/chunk-Q3MZNMCK.js +183 -0
  15. package/dist/chunk-Q3MZNMCK.js.map +1 -0
  16. package/dist/chunk-RKKRO4ZK.js +133 -0
  17. package/dist/chunk-RKKRO4ZK.js.map +1 -0
  18. package/dist/chunk-STMMFNVW.js +391 -0
  19. package/dist/chunk-STMMFNVW.js.map +1 -0
  20. package/dist/chunk-VXKONZK4.js +189 -0
  21. package/dist/chunk-VXKONZK4.js.map +1 -0
  22. package/dist/chunk-WIEGZFUO.js +337 -0
  23. package/dist/chunk-WIEGZFUO.js.map +1 -0
  24. package/dist/chunk-WND2LZ4O.js +66 -0
  25. package/dist/chunk-WND2LZ4O.js.map +1 -0
  26. package/dist/chunk-XREZY53L.js +260 -0
  27. package/dist/chunk-XREZY53L.js.map +1 -0
  28. package/dist/chunk-ZZY4WGQ6.js +13 -0
  29. package/dist/chunk-ZZY4WGQ6.js.map +1 -0
  30. package/dist/did.d.ts +182 -0
  31. package/dist/did.js +6 -0
  32. package/dist/did.js.map +1 -0
  33. package/dist/display.d.ts +117 -0
  34. package/dist/display.js +5 -0
  35. package/dist/display.js.map +1 -0
  36. package/dist/errors-BKQmNpXX.d.ts +11 -0
  37. package/dist/holder.d.ts +85 -0
  38. package/dist/holder.js +8 -0
  39. package/dist/holder.js.map +1 -0
  40. package/dist/http-BhuJ_-RZ.d.ts +25 -0
  41. package/dist/index.d.ts +15 -0
  42. package/dist/index.js +16 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/jose.d.ts +134 -0
  45. package/dist/jose.js +4 -0
  46. package/dist/jose.js.map +1 -0
  47. package/dist/oid4vci.d.ts +428 -0
  48. package/dist/oid4vci.js +11 -0
  49. package/dist/oid4vci.js.map +1 -0
  50. package/dist/oid4vp.d.ts +416 -0
  51. package/dist/oid4vp.js +11 -0
  52. package/dist/oid4vp.js.map +1 -0
  53. package/dist/profile.d.ts +218 -0
  54. package/dist/profile.js +4 -0
  55. package/dist/profile.js.map +1 -0
  56. package/dist/sdjwt.d.ts +133 -0
  57. package/dist/sdjwt.js +5 -0
  58. package/dist/sdjwt.js.map +1 -0
  59. package/dist/sender.d.ts +8 -0
  60. package/dist/sender.js +7 -0
  61. package/dist/sender.js.map +1 -0
  62. package/dist/status.d.ts +108 -0
  63. package/dist/status.js +7 -0
  64. package/dist/status.js.map +1 -0
  65. package/dist/util-DOTEZgTt.d.ts +3 -0
  66. package/dist/verify.d.ts +144 -0
  67. package/dist/verify.js +9 -0
  68. package/dist/verify.js.map +1 -0
  69. package/dist/webhook.d.ts +62 -0
  70. package/dist/webhook.js +7 -0
  71. package/dist/webhook.js.map +1 -0
  72. package/package.json +168 -4
@@ -0,0 +1,416 @@
1
+ import { DidResolver } from './did.js';
2
+ import { CredentialsKitError } from './index.js';
3
+ import { F as FetchLike } from './http-BhuJ_-RZ.js';
4
+ import { HostPolicy } from './did.js';
5
+ import { Signer } from './jose.js';
6
+ import { DcqlQuerySummary } from './profile.js';
7
+ import { ParsedSdJwt } from './sdjwt.js';
8
+ import { VerifyFailureCode, VerifiedPresentation, VerifyPolicy, VerifyDeps } from './verify.js';
9
+ import './util-DOTEZgTt.js';
10
+ import './display.js';
11
+
12
+ interface P256PublicJwk {
13
+ kty: 'EC';
14
+ crv: 'P-256';
15
+ x: string;
16
+ y: string;
17
+ kid?: string;
18
+ use?: 'enc';
19
+ alg?: 'ECDH-ES';
20
+ }
21
+ interface P256PrivateJwk extends P256PublicJwk {
22
+ d: string;
23
+ }
24
+ /** The content encryption algorithms supported, strongest first. */
25
+ declare const JWE_ENCS: readonly ["A256GCM", "A128GCM"];
26
+ type JweEnc = (typeof JWE_ENCS)[number];
27
+
28
+ /**
29
+ * `@ixo/credentials-kit/oid4vp` — OpenID for Verifiable Presentations 1.0, as profiled by
30
+ * SPEC §3 and §13.3:
31
+ *
32
+ * - signed request object (`typ: oauth-authz-req+jwt`, `alg` `EdDSA`; `Ed25519` accepted) with
33
+ * `client_id = decentralized_identifier:<did>`, signed by a key of that DID named by `kid`
34
+ * (OpenID4VP §5.9.3). The kit's verifier emits `aud: https://self-issued.me/v2` (§5.8, static
35
+ * discovery), `iat` and `exp`; the kit's wallet accepts request objects without `aud`, `iat` or
36
+ * `exp` (the spec's own examples have none) and enforces each one that is present;
37
+ * - `response_type: vp_token`, `response_mode: direct_post` or `direct_post.jwt` (§8.2, §8.3.1);
38
+ * - a DCQL subset: credential queries of format `dc+sd-jwt` with `meta.vct_values`, optional
39
+ * one-segment claim paths with optional `values`, and `path: ['iss']` + `values` as the
40
+ * accepted-issuer filter. Unknown members are ignored (§6), duplicate claim queries are
41
+ * dropped, `multiple: true` is answered with one presentation. `credential_sets`,
42
+ * `claim_sets`, `trusted_authorities`, multi-segment paths and other formats are refused with
43
+ * `unsupported_request` (and `error.feature`), which the wallet reports to the verifier with
44
+ * `sendAuthorizationError` (§8.5);
45
+ * - `vp_token`: `{ <query id>: [<SD-JWT+KB>] }`;
46
+ * - encrypted responses: an unsigned JWE (`ECDH-ES`, P-256, `enc` `A128GCM` — the spec default —
47
+ * or `A256GCM`, chosen from the verifier's `encrypted_response_enc_values_supported`) to the key
48
+ * in `client_metadata.jwks` whose payload is the response parameters (§8.3); the form body is
49
+ * `response=<jwe>`;
50
+ * - wallet invocation: `buildWalletLink` / `parseWalletLink`
51
+ * (`openid4vp://?client_id=…&request_uri=…`, §5.10.1, §9).
52
+ */
53
+
54
+ /** Static-discovery audience of a request object (OpenID4VP §5.8). */
55
+ declare const SELF_ISSUED_AUDIENCE = "https://self-issued.me/v2";
56
+ /** The `enc` the kit prefers when the verifier offers it. */
57
+ declare const RESPONSE_ENCRYPTION_ENC = "A256GCM";
58
+ /** `enc` values the kit can produce and decrypt, in the wallet's order of preference. */
59
+ declare const RESPONSE_ENCRYPTION_ENCS: readonly JweEnc[];
60
+ /** The `enc` a wallet must use when the verifier lists none (OpenID4VP §8.3). */
61
+ declare const DEFAULT_RESPONSE_ENCRYPTION_ENC: JweEnc;
62
+ /** Most credential queries / claims per query the kit accepts. */
63
+ declare const MAX_CREDENTIAL_QUERIES = 16;
64
+ declare const MAX_CLAIMS_PER_QUERY = 64;
65
+ /** Largest request object accepted (64 KiB). */
66
+ declare const MAX_REQUEST_OBJECT_LENGTH: number;
67
+ /** Largest response body accepted (256 KiB). */
68
+ declare const MAX_RESPONSE_BODY_LENGTH: number;
69
+ /** Longest lifetime of a request object the wallet accepts (from `iat`, or from now). */
70
+ declare const MAX_REQUEST_LIFETIME_SECONDS: number;
71
+ type ResponseMode = 'direct_post' | 'direct_post.jwt';
72
+ type Oid4vpErrorCode = 'malformed_request' | 'wrong_type' | 'unsupported_client_id' | 'unknown_verifier' | 'unknown_key' | 'bad_signature' | 'expired' | 'unsupported_request' | 'unsupported_response_mode' | 'insecure_response_uri'
73
+ /** No longer thrown (DCQL problems are `malformed_request` / `unsupported_request`). */
74
+ | 'unsupported_query' | 'unsupported_encryption' | 'malformed_response' | 'decryption_failed' | 'wallet_error' | 'state_mismatch';
75
+ /**
76
+ * Where a wallet may send an error response for a request whose signature it verified (the
77
+ * fields of `AuthorizationRequest` that `sendAuthorizationError` needs).
78
+ */
79
+ interface AuthorizationErrorTarget {
80
+ clientId: string;
81
+ responseUri: string;
82
+ responseMode: ResponseMode;
83
+ state?: string;
84
+ /** Present when the error can be encrypted (`direct_post.jwt` with a usable key). */
85
+ responseEncryptionJwk?: P256PublicJwk;
86
+ responseEncryptionEnc?: JweEnc;
87
+ }
88
+ declare class Oid4vpError extends CredentialsKitError {
89
+ readonly code: Oid4vpErrorCode;
90
+ /** For `wallet_error`: the OAuth error code the wallet sent (e.g. `access_denied`). */
91
+ readonly walletError?: string;
92
+ /**
93
+ * For `unsupported_request`: the feature refused (`credential_sets`, `claim_sets`,
94
+ * `trusted_authorities`, `nested_path`, `format`, `registered_claim`, `transaction_data`,
95
+ * `scope`, `response_type`, `request_uri_method`, `request`, `too_many_queries`,
96
+ * `too_many_claims`).
97
+ */
98
+ readonly feature?: string;
99
+ /**
100
+ * Set only when the request object's signature verified and its response URI is usable: the
101
+ * wallet may tell the verifier with `sendAuthorizationError({ target: error.errorTarget, … })`
102
+ * (OpenID4VP §8.5). Never set for a request that did not verify.
103
+ */
104
+ readonly errorTarget?: AuthorizationErrorTarget;
105
+ constructor(code: Oid4vpErrorCode, walletError?: string, extra?: {
106
+ feature?: string;
107
+ errorTarget?: AuthorizationErrorTarget;
108
+ });
109
+ }
110
+ interface DcqlClaimQuery {
111
+ id?: string;
112
+ /** One claim name (one-segment path). */
113
+ path: [string];
114
+ values?: (string | number | boolean)[];
115
+ }
116
+ interface DcqlCredentialQuery {
117
+ id: string;
118
+ format: 'dc+sd-jwt';
119
+ meta: {
120
+ vct_values: string[];
121
+ };
122
+ claims?: DcqlClaimQuery[];
123
+ /** Absent means true (DCQL §6.1). The kit's wallet always presents with key binding. */
124
+ require_cryptographic_holder_binding?: boolean;
125
+ /** `true` is accepted and answered with one presentation. */
126
+ multiple?: boolean;
127
+ }
128
+ interface DcqlQuery {
129
+ credentials: DcqlCredentialQuery[];
130
+ }
131
+ /**
132
+ * Validate a DCQL query against the profile's subset and return it in normal form (unknown
133
+ * members dropped, per DCQL §6 "MUST ignore any unknown properties"; duplicate claim queries
134
+ * dropped). Throws `Oid4vpError('malformed_request')` for an invalid query and
135
+ * `Oid4vpError('unsupported_request')` (with `feature`) for a valid one the profile does not
136
+ * answer.
137
+ */
138
+ declare function validateDcql(dcql: unknown): DcqlQuery;
139
+ /** What each credential query asks for, for consent screens and catalogs. Validates first. */
140
+ declare function summarizeDcql(dcql: unknown): DcqlQuerySummary[];
141
+ type MatchFailure = 'unsupported_query' | 'wrong_format' | 'wrong_type' | 'untrusted_issuer' | 'missing_claim' | 'value_mismatch' | 'no_holder_binding';
142
+ type MatchResult = {
143
+ ok: true;
144
+ disclose: string[];
145
+ } | {
146
+ ok: false;
147
+ reason: MatchFailure;
148
+ };
149
+ /**
150
+ * Whether a held credential (parsed, without KB) answers one credential query, and which
151
+ * selectively disclosable top-level claims to disclose for it (in query order). Plaintext claims
152
+ * are matched but never listed. Value restrictions are applied (DCQL §6.4.1). A requested claim
153
+ * whose value is an object with nested disclosures is disclosed at the top level only (nested
154
+ * disclosures are not released: one-segment paths only).
155
+ */
156
+ declare function matchCredential(query: unknown, parsed: ParsedSdJwt): MatchResult;
157
+ /** A fresh P-256 key pair for `direct_post.jwt` (keep `privateJwk` with the request). */
158
+ declare function generateResponseKeyPair(): Promise<{
159
+ publicJwk: P256PublicJwk;
160
+ privateJwk: P256PrivateJwk;
161
+ }>;
162
+ interface CreateAuthorizationRequestInput {
163
+ /** Signs with a key of `clientDid`; `signer.kid` must be a DID URL of `clientDid`. */
164
+ signer: Signer;
165
+ clientDid: string;
166
+ /** Where the wallet POSTs the response (https on a public host; see `allowHttp`/`allowLocal`). */
167
+ responseUri: string;
168
+ /** Fresh, random, at least 16 URL-safe characters (OpenID4VP §5.2). */
169
+ nonce: string;
170
+ /** URL-safe characters only (OpenID4VP §5.2). */
171
+ state: string;
172
+ dcql: DcqlQuery;
173
+ /**
174
+ * When given, `response_mode` is `direct_post.jwt` and the response is encrypted to it; the
175
+ * request lists `A256GCM` and `A128GCM`, both of which `parseAuthorizationResponse` decrypts.
176
+ */
177
+ responseEncryptionJwk?: P256PublicJwk;
178
+ /** Expiry, unix seconds. */
179
+ exp: number;
180
+ /** ms since the epoch (for `iat`); default `Date.now()`. */
181
+ now?: number;
182
+ /** Allow an http `responseUri` on a loopback host (local development only; needs `allowLocal`). */
183
+ allowHttp?: boolean;
184
+ /** Allow a `responseUri` on a loopback / private / local-name host (local development only). */
185
+ allowLocal?: boolean;
186
+ }
187
+ /** A signed OpenID4VP request object (compact JWS). */
188
+ declare function createAuthorizationRequest(input: CreateAuthorizationRequestInput): Promise<string>;
189
+ interface WalletLink {
190
+ /** The full client_id, to compare with the request object's (`expectedClientId`). */
191
+ clientId: string;
192
+ requestUri: string;
193
+ }
194
+ /**
195
+ * The standard Authorization Request a non-Hub wallet opens: `openid4vp://?client_id=<…>&
196
+ * request_uri=<…>` (both URL-encoded, no `request_uri_method`: GET). `scheme` is a custom scheme
197
+ * (`openid4vp://`, `haip://`, …) or an https base URL (a wallet's universal link) without query
198
+ * or fragment.
199
+ */
200
+ declare function buildWalletLink(input: {
201
+ clientId: string;
202
+ requestUri: string;
203
+ scheme?: string;
204
+ }): string;
205
+ /**
206
+ * Read a wallet link (`openid4vp://?client_id=…&request_uri=…`, or the same query on an https
207
+ * URL). Throws `Oid4vpError('malformed_request')` when `client_id` or `request_uri` is missing or
208
+ * repeated, or when `request_uri` fails the kit's URL rules (`isFetchableUrl`: https on a public
209
+ * host, no credentials or fragment; `opts.allowHttp` / `opts.allowLocal` for local development
210
+ * only), and `unsupported_request` for a request by value (`request`) or
211
+ * `request_uri_method=post`. Fetch the request object with no redirects and a timeout, then pass
212
+ * `clientId` as `expectedClientId` to `verifyAuthorizationRequest` (§5.10.1: they MUST be
213
+ * identical).
214
+ */
215
+ declare function parseWalletLink(link: string, opts?: HostPolicy): WalletLink;
216
+ interface AuthorizationRequest {
217
+ /** The request object as received. */
218
+ jwt: string;
219
+ /** The full client_id (`decentralized_identifier:<did>`): the KB-JWT `aud`. */
220
+ clientId: string;
221
+ clientDid: string;
222
+ /** The verification method that signed the request. */
223
+ kid: string;
224
+ responseUri: string;
225
+ responseMode: ResponseMode;
226
+ nonce: string;
227
+ state?: string;
228
+ dcql: DcqlQuery;
229
+ /** The key the response must be encrypted to (`direct_post.jwt`). */
230
+ responseEncryptionJwk?: P256PublicJwk;
231
+ /** The `enc` the wallet uses for `direct_post.jwt` (chosen from the verifier's list). */
232
+ responseEncryptionEnc?: JweEnc;
233
+ /** unix seconds; absent when the request object has no `exp`. */
234
+ exp?: number;
235
+ iat?: number;
236
+ }
237
+ interface VerifyAuthorizationRequestOptions {
238
+ resolver: DidResolver;
239
+ /** ms since the epoch; default `Date.now()`. */
240
+ now?: number;
241
+ /** Accept an http `response_uri` on a loopback host (local development only; needs `allowLocal`). */
242
+ allowHttp?: boolean;
243
+ /** Accept a `response_uri` on a loopback / private / local-name host (local development only). */
244
+ allowLocal?: boolean;
245
+ /**
246
+ * The `client_id` of the Authorization Request that pointed here (`parseWalletLink`): the
247
+ * request object's must be identical (§5.10.1), else `malformed_request`.
248
+ */
249
+ expectedClientId?: string;
250
+ /** Refuse a request object without `exp` (the Credentials worker's deposit rule). Default false. */
251
+ requireExpiry?: boolean;
252
+ }
253
+ /**
254
+ * Verify a request object as a wallet (or the Credentials worker) must before acting on it:
255
+ * typ, client_id (and `expectedClientId`), `aud`/`iat`/`exp` when present (lifetime at most
256
+ * 24 h), the signature by a key of the client_id DID named by `kid` (listed under
257
+ * `authentication` or `assertionMethod`, controlled by that DID), then the supported response
258
+ * mode, a public https response URI, nonce and state, encryption parameters and DCQL. Throws
259
+ * `Oid4vpError` (with `errorTarget` when the verifier can be told, see `sendAuthorizationError`);
260
+ * `ResolverUnavailable` propagates.
261
+ */
262
+ declare function verifyAuthorizationRequest(jwt: string, opts: VerifyAuthorizationRequestOptions): Promise<AuthorizationRequest>;
263
+ /**
264
+ * The request a verifier created, read back from its own JWT WITHOUT checking the signature or
265
+ * the clock (use only for a request object you produced and stored yourself).
266
+ */
267
+ declare function decodeOwnAuthorizationRequest(jwt: string, opts?: HostPolicy): AuthorizationRequest;
268
+ interface CreatePresentationInput {
269
+ /** The held SD-JWT (as issued: `<jwt>~<disclosures>~`). */
270
+ sdjwt: string;
271
+ /** Claim names to disclose (from `matchCredential`). */
272
+ disclose: readonly string[];
273
+ /** The holder key the credential's `cnf` names. */
274
+ signer: Pick<Signer, 'sign'>;
275
+ /** The verifier's full client_id. */
276
+ audience: string;
277
+ nonce: string;
278
+ /** ms since the epoch; default `Date.now()`. */
279
+ now?: number;
280
+ }
281
+ /** An SD-JWT+KB with only the chosen disclosures and a fresh KB-JWT (RFC 9901 §4.3). */
282
+ declare function createPresentation(input: CreatePresentationInput): Promise<string>;
283
+ /** `{ <query id>: [<presentation>] }` */
284
+ type VpToken = Record<string, string[]>;
285
+ interface AuthorizationResponse {
286
+ url: string;
287
+ /** `application/x-www-form-urlencoded` body. */
288
+ body: string;
289
+ contentType: 'application/x-www-form-urlencoded';
290
+ }
291
+ /**
292
+ * The POST the wallet sends to the response URI: form-encoded `vp_token` (JSON) + `state`, or,
293
+ * for `direct_post.jwt`, `response=<JWE>` (the `enc` the request chose) whose payload carries
294
+ * `vp_token` and `state`.
295
+ */
296
+ declare function createAuthorizationResponse(input: {
297
+ request: AuthorizationRequest;
298
+ vpToken: VpToken;
299
+ }): Promise<AuthorizationResponse>;
300
+ /** OpenID4VP §8.5 / RFC 6749 §4.1.2.1 error codes a wallet sends. */
301
+ type AuthorizationErrorCode = 'invalid_request' | 'access_denied' | 'invalid_client' | 'invalid_scope' | 'vp_formats_not_supported' | 'invalid_request_uri_method' | 'invalid_transaction_data' | 'wallet_unavailable';
302
+ /**
303
+ * The §8.5 error code for a refusal `verifyAuthorizationRequest` threw WITH an `errorTarget`;
304
+ * null when the verifier is not to be told (no target: the request did not verify).
305
+ */
306
+ declare function authorizationErrorFor(e: unknown): AuthorizationErrorCode | null;
307
+ /**
308
+ * The form body of an error response (§8.5, §8.2): `error`, `error_description`, `state`;
309
+ * encrypted as `response=<JWE>` for `direct_post.jwt` when the target has a usable key, else
310
+ * plain (§8.3.1 allows an unencrypted error response). `errorDescription` must be RFC 6749
311
+ * characters (printable ASCII without `"` and `\`), at most 300; never put personal data in it.
312
+ */
313
+ declare function createAuthorizationErrorResponse(input: {
314
+ target: AuthorizationRequest | AuthorizationErrorTarget;
315
+ error: AuthorizationErrorCode;
316
+ errorDescription?: string;
317
+ }): Promise<AuthorizationResponse>;
318
+ interface SendAuthorizationErrorInput extends HostPolicy {
319
+ /** A verified request, or `error.errorTarget` of a refusal. */
320
+ target: AuthorizationRequest | AuthorizationErrorTarget;
321
+ error: AuthorizationErrorCode;
322
+ errorDescription?: string;
323
+ fetch: FetchLike;
324
+ timeoutMs?: number;
325
+ }
326
+ /**
327
+ * Tell the verifier the request will not be answered (OpenID4VP §8.5): POST the error response
328
+ * to its response URI (no redirects, timeout, capped answer). Privacy (§15.9): do not send an
329
+ * error that reveals whether a matching credential exists before the person has decided; use
330
+ * `access_denied` after they declined. Returns `{ delivered, status, redirectUri? }`
331
+ * (`delivered` = HTTP 200; `status` null when unreachable). Throws `TypeError` for a bad code or
332
+ * description, `Oid4vpError('insecure_response_uri')` when the URI fails the host policy.
333
+ */
334
+ declare function sendAuthorizationError(input: SendAuthorizationErrorInput): Promise<{
335
+ delivered: boolean;
336
+ status: number | null;
337
+ redirectUri?: string;
338
+ }>;
339
+ interface ParsedAuthorizationResponse {
340
+ vpToken: VpToken;
341
+ state?: string;
342
+ }
343
+ /**
344
+ * Read the wallet's POST body (form-encoded string or `URLSearchParams`). With `decryptionKey`
345
+ * the body MUST be `response=<JWE>` (`A128GCM` or `A256GCM`; an unencrypted response is
346
+ * refused); without it the body must be `vp_token=…`. Pass your `request` to make the key
347
+ * mandatory for a `direct_post.jwt` request (TypeError without it). A wallet error response
348
+ * (encrypted or not, §8.3.1) throws `Oid4vpError('wallet_error')` carrying the OAuth error code.
349
+ */
350
+ declare function parseAuthorizationResponse(body: string | URLSearchParams, opts?: {
351
+ decryptionKey?: P256PrivateJwk;
352
+ request?: AuthorizationRequest;
353
+ }): Promise<ParsedAuthorizationResponse>;
354
+ type ResponseFailureCode = VerifyFailureCode | 'missing_presentation' | 'unexpected_presentation' | 'missing_claim' | 'value_mismatch';
355
+ interface FailedQuery {
356
+ ok: false;
357
+ code: ResponseFailureCode;
358
+ /**
359
+ * True when the person you expected (`expectedSubject` in `policyFor`, matched) is proven to
360
+ * have sent this presentation for this request's nonce, and it still does not meet the policy
361
+ * or query. Always false when the policy has no `expectedSubject`. See `FailedPresentation`.
362
+ */
363
+ holderAuthenticated: boolean;
364
+ /**
365
+ * True when the KB-JWT verified for this request's nonce and audience with the presented
366
+ * credential's own `cnf` key: its holder answered, whoever that is. Never close on it alone.
367
+ */
368
+ keyBindingValid: boolean;
369
+ }
370
+ type QueryResult = VerifiedPresentation | FailedQuery;
371
+ interface VerifyAuthorizationResponseInput {
372
+ vpToken: VpToken;
373
+ /** The request (from `verifyAuthorizationRequest` / `decodeOwnAuthorizationRequest`), or your own request JWT. */
374
+ request: AuthorizationRequest | string;
375
+ /** The verifier's policy for one credential query (audience, nonce and key binding are set from the request). */
376
+ policyFor: (queryId: string) => Omit<VerifyPolicy, 'audience' | 'nonce' | 'requireKeyBinding'>;
377
+ deps: VerifyDeps;
378
+ /** The `state` the response carried; must equal the request's (required when the request has one). */
379
+ state?: string;
380
+ }
381
+ interface VerifiedAuthorizationResponse {
382
+ /** True only when every credential query was answered and verified. */
383
+ ok: boolean;
384
+ results: Record<string, QueryResult>;
385
+ /**
386
+ * True when every query's policy named `expectedSubject` and every result is either verified
387
+ * or a failure after that person was authenticated: the answer certainly came from the person
388
+ * you asked (close the request). False when any part could have come from someone else (keep
389
+ * the request open), and ALWAYS false when a policy has no `expectedSubject`: anyone holding a
390
+ * credential from an accepted issuer can answer such a request (OpenID4VP §14.2; for
391
+ * subject-less flows bind the answer to the browser session with a redirect URI and response
392
+ * code instead).
393
+ */
394
+ holderAuthenticated: boolean;
395
+ /**
396
+ * True when every result is either verified or a failure after the key binding held: each
397
+ * presentation was signed by the holder of the credential it carries, for this nonce and
398
+ * audience. It says nothing about who that holder is.
399
+ */
400
+ keyBindingValid: boolean;
401
+ }
402
+ /**
403
+ * Verify every presentation in a `vp_token` against the request: one presentation per credential
404
+ * query, each verified with `verifyPresentation` (KB-JWT `aud` = the request's client_id, `nonce`
405
+ * = its nonce, key binding required), each meeting its query (vct, accepted issuers, every
406
+ * requested claim present and, when `values` is given, matching; a requested `sub` or `iat` is
407
+ * read from the issuer-signed credential), and all of them from the same holder (`sub` and
408
+ * `cnf`). `ok` is true only when every query passed. Pass `expectedSubject` in every policy:
409
+ * without it `holderAuthenticated` is false. Throws
410
+ * `VerificationUnavailable` when a dependency is down and `Oid4vpError('state_mismatch')` when
411
+ * the state differs from the request's (or is missing while the request has one).
412
+ */
413
+ declare function verifyAuthorizationResponse(input: VerifyAuthorizationResponseInput): Promise<VerifiedAuthorizationResponse>;
414
+
415
+ export { DEFAULT_RESPONSE_ENCRYPTION_ENC, FetchLike, MAX_CLAIMS_PER_QUERY, MAX_CREDENTIAL_QUERIES, MAX_REQUEST_LIFETIME_SECONDS, MAX_REQUEST_OBJECT_LENGTH, MAX_RESPONSE_BODY_LENGTH, Oid4vpError, RESPONSE_ENCRYPTION_ENC, RESPONSE_ENCRYPTION_ENCS, SELF_ISSUED_AUDIENCE, authorizationErrorFor, buildWalletLink, createAuthorizationErrorResponse, createAuthorizationRequest, createAuthorizationResponse, createPresentation, decodeOwnAuthorizationRequest, generateResponseKeyPair, matchCredential, parseAuthorizationResponse, parseWalletLink, sendAuthorizationError, summarizeDcql, validateDcql, verifyAuthorizationRequest, verifyAuthorizationResponse };
416
+ export type { AuthorizationErrorCode, AuthorizationErrorTarget, AuthorizationRequest, AuthorizationResponse, CreateAuthorizationRequestInput, CreatePresentationInput, DcqlClaimQuery, DcqlCredentialQuery, DcqlQuery, FailedQuery, JweEnc, MatchFailure, MatchResult, Oid4vpErrorCode, P256PrivateJwk, P256PublicJwk, ParsedAuthorizationResponse, QueryResult, ResponseFailureCode, ResponseMode, SendAuthorizationErrorInput, VerifiedAuthorizationResponse, VerifyAuthorizationRequestOptions, VerifyAuthorizationResponseInput, VpToken, WalletLink };
package/dist/oid4vp.js ADDED
@@ -0,0 +1,11 @@
1
+ export { DEFAULT_RESPONSE_ENCRYPTION_ENC, MAX_CLAIMS_PER_QUERY, MAX_CREDENTIAL_QUERIES, MAX_REQUEST_LIFETIME_SECONDS, MAX_REQUEST_OBJECT_LENGTH, MAX_RESPONSE_BODY_LENGTH, Oid4vpError, RESPONSE_ENCRYPTION_ENC, RESPONSE_ENCRYPTION_ENCS, SELF_ISSUED_AUDIENCE, authorizationErrorFor, buildWalletLink, createAuthorizationErrorResponse, createAuthorizationRequest, createAuthorizationResponse, createPresentation, decodeOwnAuthorizationRequest, generateResponseKeyPair, matchCredential, parseAuthorizationResponse, parseWalletLink, sendAuthorizationError, summarizeDcql, validateDcql, verifyAuthorizationRequest, verifyAuthorizationResponse } from './chunk-2SF56NEJ.js';
2
+ import './chunk-I6GBYFIJ.js';
3
+ import './chunk-STMMFNVW.js';
4
+ import './chunk-XREZY53L.js';
5
+ import './chunk-JBUX6V2Q.js';
6
+ import './chunk-WIEGZFUO.js';
7
+ import './chunk-Q3MZNMCK.js';
8
+ import './chunk-VXKONZK4.js';
9
+ import './chunk-AQ3IINHC.js';
10
+ //# sourceMappingURL=oid4vp.js.map
11
+ //# sourceMappingURL=oid4vp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"oid4vp.js"}
@@ -0,0 +1,218 @@
1
+ import { CardDisplay } from './display.js';
2
+ import './http-BhuJ_-RZ.js';
3
+
4
+ /** The UCAN resource of the Credentials worker; the caller acts as itself. */
5
+ declare const UCAN_RESOURCE = "ixo:credentials";
6
+ /** `ixo:credentials/<entity DID>`: the caller acts as that entity (SPEC §5.1). */
7
+ declare function entityResource(entityDid: string): string;
8
+ declare const ABILITY_ISSUE = "credentials/issue";
9
+ declare const ABILITY_VERIFY = "credentials/verify";
10
+ declare const ABILITY_HOLD = "credentials/hold";
11
+ /** Consent: the holder lets an issuer deposit offers that the wallet may store automatically. */
12
+ declare const ABILITY_OFFER = "credentials/offer";
13
+ /** Standing presentation consent: the holder lets a verifier be answered without asking. */
14
+ declare const ABILITY_PRESENT = "credentials/present";
15
+ declare const ABILITIES: {
16
+ readonly issue: "credentials/issue";
17
+ readonly verify: "credentials/verify";
18
+ readonly hold: "credentials/hold";
19
+ readonly offer: "credentials/offer";
20
+ readonly present: "credentials/present";
21
+ };
22
+ type Ability = (typeof ABILITIES)[keyof typeof ABILITIES];
23
+ declare const CREDENTIAL_FORMAT = "dc+sd-jwt";
24
+ declare const SD_JWT_TYP = "dc+sd-jwt";
25
+ declare const KB_JWT_TYP = "kb+jwt";
26
+ declare const STATUS_LIST_JWT_TYP = "statuslist+jwt";
27
+ declare const REQUEST_OBJECT_TYP = "oauth-authz-req+jwt";
28
+ declare const PROOF_JWT_TYP = "openid4vci-proof+jwt";
29
+ declare const MEDIA_TYPES: {
30
+ readonly statusList: "application/statuslist+jwt";
31
+ readonly requestObject: "application/oauth-authz-req+jwt";
32
+ readonly json: "application/json";
33
+ readonly form: "application/x-www-form-urlencoded";
34
+ };
35
+ /** OpenID4VP Client Identifier Prefix for DID verifiers. */
36
+ declare const CLIENT_ID_PREFIX = "decentralized_identifier:";
37
+ /** OAuth grant type of the OpenID4VCI pre-authorized code flow. */
38
+ declare const PRE_AUTHORIZED_CODE_GRANT = "urn:ietf:params:oauth:grant-type:pre-authorized_code";
39
+ /** Webhook signature header (Credentials worker → Hub). */
40
+ declare const WEBHOOK_SIGNATURE_HEADER = "x-ixo-signature";
41
+ declare const HEADERS: {
42
+ readonly webhookSignature: "x-ixo-signature";
43
+ readonly authorization: "authorization";
44
+ };
45
+ declare const VAULT_CREDENTIAL_EVENT_TYPE = "ixo.credential";
46
+ declare const VAULT_CREDENTIAL_INDEX_TYPE = "ixo.credential.index";
47
+ declare const VAULT_CREDENTIAL_CONTENT_FIELD = "credential";
48
+ /**
49
+ * Vault index state keys of the known credential types, by their FULL `vct` (exact match). These
50
+ * slots are shared with Self's web app (`identitylevel1`) and the portal (`kycamllevel1`).
51
+ */
52
+ declare const VCT_STATE_KEYS: Readonly<Record<string, string>>;
53
+ /**
54
+ * The Vault index state key for a `vct`, from the FULL `vct` (exact match, no normalising): a
55
+ * known type's slot from `VCT_STATE_KEYS` (`IDENTITY_LEVEL1_VCT` → `identitylevel1`,
56
+ * `KYC_AML_LEVEL1_VCT` → `kycamllevel1`), else `vct-` + the first 32 hex characters of
57
+ * SHA-256(vct). Two different `vct` values never share a slot, so a foreign issuer's look-alike
58
+ * type (`https://evil.example/Identity-Level_1.json`) cannot land in a known type's slot. Throws
59
+ * `TypeError` for an empty or non-string `vct`.
60
+ */
61
+ declare function stateKeyForVct(vct: string): string;
62
+ /** Self's identity credential type (unchanged in v1). */
63
+ declare const IDENTITY_LEVEL1_VCT = "https://credentials.ixo.world/types/IdentityLevel1";
64
+ /** The portal's KYC/AML credential type (pay-convert-oracle `KYC_VCT`). */
65
+ declare const KYC_AML_LEVEL1_VCT = "https://github.com/ixofoundation/ns/blob/main/protocol/credentials/v1/KYCAMLLevel1.json";
66
+ /** Self's OpenID4VCI credential configuration id. */
67
+ declare const IDENTITY_LEVEL1_CONFIGURATION_ID = "IdentityLevel1";
68
+ /** Derived age claims a credential with a birth date carries, each its own disclosure. */
69
+ declare const AGE_CLAIMS: readonly ["age_over_18", "age_over_21", "age_birth_year"];
70
+ type AgeClaim = (typeof AGE_CLAIMS)[number];
71
+ /** Registered / structural claims that are never selectively disclosable in the profile. */
72
+ declare const REGISTERED_CLAIMS: readonly ["iss", "sub", "iat", "nbf", "exp", "vct", "vct#integrity", "cnf", "status", "_sd", "_sd_alg"];
73
+ type ClaimDisclosure = 'always' | 'allowed' | 'never';
74
+ interface CatalogClaim {
75
+ name: string;
76
+ label: string;
77
+ /** Whether the claim is selectively disclosable. */
78
+ sd: ClaimDisclosure;
79
+ }
80
+ interface CatalogIssuerType {
81
+ vct: string;
82
+ name: string;
83
+ description?: string;
84
+ type_metadata_uri?: string;
85
+ claims: CatalogClaim[];
86
+ /** The card look for credentials of this type (SPEC §15.1; validated, unknown members dropped). */
87
+ display?: CardDisplay;
88
+ }
89
+ interface CatalogIssuerEntry {
90
+ did: string;
91
+ name: string;
92
+ description?: string;
93
+ url?: string;
94
+ /** The OpenID4VCI Credential Issuer Identifier (https URL). */
95
+ credential_issuer: string;
96
+ types: CatalogIssuerType[];
97
+ /** The issuer's mark (https image URL; png, jpeg or webp). */
98
+ logo_uri?: string;
99
+ /** The issuer's mark colour, `#rrggbb`. */
100
+ color?: string;
101
+ }
102
+ interface CatalogVerifierAccept {
103
+ purpose: string;
104
+ vct: string;
105
+ claims: string[];
106
+ issuers: string[];
107
+ }
108
+ interface CatalogVerifierEntry {
109
+ did: string;
110
+ name: string;
111
+ description?: string;
112
+ url?: string;
113
+ accepts: CatalogVerifierAccept[];
114
+ /** The verifier's mark (https image URL; png, jpeg or webp). */
115
+ logo_uri?: string;
116
+ /** The verifier's mark colour, `#rrggbb`. */
117
+ color?: string;
118
+ }
119
+ type OfferStatus = 'pending' | 'accepted' | 'declined' | 'retracted' | 'expired';
120
+ type RequestStatus = 'pending' | 'answered' | 'declined' | 'cancelled' | 'expired';
121
+ /**
122
+ * An offer's `display`: name, type and description only (SPEC §16.1). The card look, the issuer's
123
+ * name and its logo come only from the issuer's catalog entry (`CatalogIssuerEntry`), so an offer
124
+ * cannot change them; the worker drops anything else and lists it in `display_dropped`.
125
+ */
126
+ interface OfferDisplay {
127
+ name: string;
128
+ vct: string;
129
+ description?: string;
130
+ }
131
+ /** An offer as the worker lists it (never the pre-authorized code). */
132
+ interface OfferSummary {
133
+ id: string;
134
+ issuer: string;
135
+ subject: string;
136
+ ref: string;
137
+ credential_issuer: string;
138
+ vct: string;
139
+ display: OfferDisplay;
140
+ status: OfferStatus;
141
+ /** Whether a valid `credentials/offer` delegation from the subject came with the offer. */
142
+ consent: 'valid' | 'none';
143
+ /** unix seconds */
144
+ created_at: number;
145
+ /** unix seconds */
146
+ expires_at: number;
147
+ }
148
+ /** One credential query of a request, as `summarizeDcql` reports it. */
149
+ interface DcqlQuerySummary {
150
+ id: string;
151
+ vctValues: string[];
152
+ /** Claim names asked for (never `iss`). */
153
+ claims: string[];
154
+ /** The accepted-issuer filter, when the query has one. */
155
+ issuers?: string[];
156
+ }
157
+ /** A presentation request as the worker lists it. */
158
+ interface RequestSummary {
159
+ id: string;
160
+ verifier: string;
161
+ subject: string;
162
+ ref: string;
163
+ /** The verifier's full OpenID4VP client_id (`decentralized_identifier:<did>`). */
164
+ client_id: string;
165
+ purpose: string;
166
+ summary: DcqlQuerySummary[];
167
+ /** Host of the request's `response_uri`. */
168
+ response_host: string;
169
+ status: RequestStatus;
170
+ /** unix seconds */
171
+ created_at: number;
172
+ /** unix seconds */
173
+ expires_at: number;
174
+ }
175
+ /** One entry of a person's block list (`GET /v1/blocks`). */
176
+ interface SenderBlock {
177
+ /** The blocked DID, exactly as written: the block covers exactly this DID (SPEC §17.4). */
178
+ sender: string;
179
+ /** unix seconds */
180
+ created_at: number;
181
+ }
182
+ /** `POST /v1/blocks` answer. */
183
+ interface BlockSenderResult extends SenderBlock {
184
+ /** Waiting offers + requests from this sender for the person, closed as declined by this call. */
185
+ closed: number;
186
+ }
187
+ /** `POST /v1/blocks/remove` answer. */
188
+ interface UnblockSenderResult {
189
+ sender: string;
190
+ /** False when the sender was not blocked. */
191
+ removed: boolean;
192
+ }
193
+ /** `GET /v1/blocks` answer (newest first). */
194
+ interface SenderBlockList {
195
+ items: SenderBlock[];
196
+ next_cursor: string | null;
197
+ }
198
+ /** At most this many blocks per person (`too_many_blocks` above it). */
199
+ declare const MAX_BLOCKS_PER_PERSON = 500;
200
+ /** The worker's error code for a deposit from a sender the person blocked (HTTP 403). */
201
+ declare const BLOCKED_ERROR = "blocked";
202
+ declare const WEBHOOK_EVENT_TYPES: readonly ["offer.created", "request.created", "offer.retracted", "request.cancelled"];
203
+ type WebhookEventType = (typeof WEBHOOK_EVENT_TYPES)[number];
204
+ /** The webhook body. It carries no secret: the Hub fetches details itself. */
205
+ interface WebhookEvent {
206
+ /** `evt_…` */
207
+ id: string;
208
+ type: WebhookEventType;
209
+ /** The holder DID the offer / request is for. */
210
+ subject: string;
211
+ /** The offer or request id (`ofr_…` / `req_…`), NOT the issuer's / verifier's `ref`. */
212
+ object_id: string;
213
+ /** unix seconds */
214
+ created_at: number;
215
+ }
216
+
217
+ export { ABILITIES, ABILITY_HOLD, ABILITY_ISSUE, ABILITY_OFFER, ABILITY_PRESENT, ABILITY_VERIFY, AGE_CLAIMS, BLOCKED_ERROR, CLIENT_ID_PREFIX, CREDENTIAL_FORMAT, CardDisplay, HEADERS, IDENTITY_LEVEL1_CONFIGURATION_ID, IDENTITY_LEVEL1_VCT, KB_JWT_TYP, KYC_AML_LEVEL1_VCT, MAX_BLOCKS_PER_PERSON, MEDIA_TYPES, PRE_AUTHORIZED_CODE_GRANT, PROOF_JWT_TYP, REGISTERED_CLAIMS, REQUEST_OBJECT_TYP, SD_JWT_TYP, STATUS_LIST_JWT_TYP, UCAN_RESOURCE, VAULT_CREDENTIAL_CONTENT_FIELD, VAULT_CREDENTIAL_EVENT_TYPE, VAULT_CREDENTIAL_INDEX_TYPE, VCT_STATE_KEYS, WEBHOOK_EVENT_TYPES, WEBHOOK_SIGNATURE_HEADER, entityResource, stateKeyForVct };
218
+ export type { Ability, AgeClaim, BlockSenderResult, CatalogClaim, CatalogIssuerEntry, CatalogIssuerType, CatalogVerifierAccept, CatalogVerifierEntry, ClaimDisclosure, DcqlQuerySummary, OfferDisplay, OfferStatus, OfferSummary, RequestStatus, RequestSummary, SenderBlock, SenderBlockList, UnblockSenderResult, WebhookEvent, WebhookEventType };
@@ -0,0 +1,4 @@
1
+ export { ABILITIES, ABILITY_HOLD, ABILITY_ISSUE, ABILITY_OFFER, ABILITY_PRESENT, ABILITY_VERIFY, AGE_CLAIMS, BLOCKED_ERROR, CLIENT_ID_PREFIX, CREDENTIAL_FORMAT, HEADERS, IDENTITY_LEVEL1_CONFIGURATION_ID, IDENTITY_LEVEL1_VCT, KB_JWT_TYP, KYC_AML_LEVEL1_VCT, MAX_BLOCKS_PER_PERSON, MEDIA_TYPES, PRE_AUTHORIZED_CODE_GRANT, PROOF_JWT_TYP, REGISTERED_CLAIMS, REQUEST_OBJECT_TYP, SD_JWT_TYP, STATUS_LIST_JWT_TYP, UCAN_RESOURCE, VAULT_CREDENTIAL_CONTENT_FIELD, VAULT_CREDENTIAL_EVENT_TYPE, VAULT_CREDENTIAL_INDEX_TYPE, VCT_STATE_KEYS, WEBHOOK_EVENT_TYPES, WEBHOOK_SIGNATURE_HEADER, entityResource, stateKeyForVct } from './chunk-I6GBYFIJ.js';
2
+ import './chunk-AQ3IINHC.js';
3
+ //# sourceMappingURL=profile.js.map
4
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"profile.js"}