@interop/wallet-request 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 (75) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +160 -0
  3. package/dist/appKey.d.ts +295 -0
  4. package/dist/appKey.d.ts.map +1 -0
  5. package/dist/appKey.js +516 -0
  6. package/dist/appKey.js.map +1 -0
  7. package/dist/capabilityRequest.d.ts +41 -0
  8. package/dist/capabilityRequest.d.ts.map +1 -0
  9. package/dist/capabilityRequest.js +46 -0
  10. package/dist/capabilityRequest.js.map +1 -0
  11. package/dist/classify.d.ts +233 -0
  12. package/dist/classify.d.ts.map +1 -0
  13. package/dist/classify.js +419 -0
  14. package/dist/classify.js.map +1 -0
  15. package/dist/composeVp.d.ts +52 -0
  16. package/dist/composeVp.d.ts.map +1 -0
  17. package/dist/composeVp.js +176 -0
  18. package/dist/composeVp.js.map +1 -0
  19. package/dist/ephemeralExchange.d.ts +100 -0
  20. package/dist/ephemeralExchange.d.ts.map +1 -0
  21. package/dist/ephemeralExchange.js +230 -0
  22. package/dist/ephemeralExchange.js.map +1 -0
  23. package/dist/exchangeClient.d.ts +142 -0
  24. package/dist/exchangeClient.d.ts.map +1 -0
  25. package/dist/exchangeClient.js +241 -0
  26. package/dist/exchangeClient.js.map +1 -0
  27. package/dist/index.d.ts +63 -0
  28. package/dist/index.d.ts.map +1 -0
  29. package/dist/index.js +62 -0
  30. package/dist/index.js.map +1 -0
  31. package/dist/interactionRequest.d.ts +23 -0
  32. package/dist/interactionRequest.d.ts.map +1 -0
  33. package/dist/interactionRequest.js +46 -0
  34. package/dist/interactionRequest.js.map +1 -0
  35. package/dist/interactionUrl.d.ts +42 -0
  36. package/dist/interactionUrl.d.ts.map +1 -0
  37. package/dist/interactionUrl.js +104 -0
  38. package/dist/interactionUrl.js.map +1 -0
  39. package/dist/log.d.ts +49 -0
  40. package/dist/log.d.ts.map +1 -0
  41. package/dist/log.js +53 -0
  42. package/dist/log.js.map +1 -0
  43. package/dist/matching.d.ts +95 -0
  44. package/dist/matching.d.ts.map +1 -0
  45. package/dist/matching.js +205 -0
  46. package/dist/matching.js.map +1 -0
  47. package/dist/onboarding.d.ts +96 -0
  48. package/dist/onboarding.d.ts.map +1 -0
  49. package/dist/onboarding.js +174 -0
  50. package/dist/onboarding.js.map +1 -0
  51. package/dist/parse.d.ts +63 -0
  52. package/dist/parse.d.ts.map +1 -0
  53. package/dist/parse.js +153 -0
  54. package/dist/parse.js.map +1 -0
  55. package/dist/presentationSuite.d.ts +71 -0
  56. package/dist/presentationSuite.d.ts.map +1 -0
  57. package/dist/presentationSuite.js +143 -0
  58. package/dist/presentationSuite.js.map +1 -0
  59. package/dist/processRequest.d.ts +45 -0
  60. package/dist/processRequest.d.ts.map +1 -0
  61. package/dist/processRequest.js +146 -0
  62. package/dist/processRequest.js.map +1 -0
  63. package/dist/queryPredicates.d.ts +112 -0
  64. package/dist/queryPredicates.d.ts.map +1 -0
  65. package/dist/queryPredicates.js +157 -0
  66. package/dist/queryPredicates.js.map +1 -0
  67. package/dist/types.d.ts +257 -0
  68. package/dist/types.d.ts.map +1 -0
  69. package/dist/types.js +2 -0
  70. package/dist/types.js.map +1 -0
  71. package/dist/walletInput.d.ts +118 -0
  72. package/dist/walletInput.d.ts.map +1 -0
  73. package/dist/walletInput.js +169 -0
  74. package/dist/walletInput.js.map +1 -0
  75. package/package.json +98 -0
@@ -0,0 +1,233 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * Classification of incoming VC API messages: turns a raw CHAPI event (or a QR
6
+ * / pasted payload) into a typed `IVPRequest` / `IVPOffer`, and provides the
7
+ * helpers used to dispatch on what was actually asked for (VC sharing, DID
8
+ * Authentication, capability delegation, or a combination).
9
+ *
10
+ * Ported from Freewallet's `src/lib/walletRequest/classify.ts` (the superset of
11
+ * DCW's `app/lib/exchanges.ts` / `walletRequestApi.ts` dispatch helpers). The
12
+ * shared classifier covers the three VPR-spec query types plus the App Connect
13
+ * `AppConnectQuery` extension (`appConnectRequestOf`), whose `app` block is
14
+ * validated here against the attested requesting origin.
15
+ */
16
+ import type { CHAPIStoreEvent, IAppConnectRequest, ICapabilityQueryDetail, ICredentialQuery, IQueryByExample, IVPOffer, IVPRequest, IVPRDetails, IVPRQuery, IVerifiableCredential, IVerifiablePresentation, WalletRequestProfile } from './types.js';
17
+ import type { CHAPIGetEvent } from './types.js';
18
+ import { isZcapQuery } from './queryPredicates.js';
19
+ export { isZcapQuery };
20
+ /**
21
+ * The VC data model version a presentation carrying the given credentials must
22
+ * use, so its `@context` stays coherent with what it carries: `2.0` when any
23
+ * credential is a VC 2.0 one, else `1.0`. Shared by the bare-credential
24
+ * wrapping below and by the unsigned branch of `composeVp` (the signed branch
25
+ * takes its version from the negotiated cryptosuite instead).
26
+ *
27
+ * @param credentials {IVerifiableCredential[]}
28
+ * @returns {number}
29
+ */
30
+ export declare function presentationVersionFor(credentials: IVerifiableCredential[]): number;
31
+ /**
32
+ * The Verifiable Credentials carried by a presentation, normalized to an array.
33
+ *
34
+ * @param presentation {IVerifiablePresentation}
35
+ * @returns {IVerifiableCredential[]}
36
+ */
37
+ export declare function credentialsOf(presentation: IVerifiablePresentation): IVerifiableCredential[];
38
+ /**
39
+ * Wraps a CHAPI get event as an `IVPRequest`.
40
+ *
41
+ * @param event {CHAPIGetEvent}
42
+ * @returns {IVPRequest}
43
+ */
44
+ export declare function classifyCHAPIGetEvent(event: CHAPIGetEvent): IVPRequest;
45
+ /**
46
+ * Wraps a CHAPI store event as an `IVPOffer`. A bare offered credential is
47
+ * wrapped in an unsigned presentation, so downstream code always sees a VP.
48
+ *
49
+ * @param event {CHAPIStoreEvent}
50
+ * @returns {IVPOffer}
51
+ */
52
+ export declare function classifyCHAPIStoreEvent(event: CHAPIStoreEvent): IVPOffer;
53
+ /**
54
+ * Returns true if the query set contains a `DIDAuthentication` query. Throws if
55
+ * more than one is present -- a single DID-Auth proof answers the request.
56
+ *
57
+ * @param options {object}
58
+ * @param options.queries {IVPRQuery[]}
59
+ * @returns {boolean}
60
+ */
61
+ export declare function isDIDAuthRequested({ queries }: {
62
+ queries: IVPRQuery[];
63
+ }): boolean;
64
+ /**
65
+ * Normalizes a VPR's `query` (which may be a single object or an array) to an
66
+ * array, dropping anything that is not a typed query object. A VPR body can
67
+ * legitimately carry no queries at all -- a CHAPI request that names a
68
+ * `protocols` exchange sends an empty body -- so callers get an empty array
69
+ * rather than an array holding `undefined`.
70
+ *
71
+ * @param request {IVPRDetails}
72
+ * @returns {IVPRQuery[]}
73
+ */
74
+ export declare function queriesOf(request: IVPRDetails): IVPRQuery[];
75
+ /**
76
+ * Normalizes a `QueryByExample`'s `credentialQuery` (a single detail object or
77
+ * an array of them) to an array.
78
+ *
79
+ * @param query {IQueryByExample}
80
+ * @returns {ICredentialQuery[]}
81
+ */
82
+ export declare function credentialQueriesOf(query: IQueryByExample): ICredentialQuery[];
83
+ /**
84
+ * Collects the requested capabilities from a query set: filters the two zcap
85
+ * query type strings (`AuthorizationCapabilityQuery` canonical, `ZcapQuery`
86
+ * legacy alias), normalizes each `capabilityQuery` (object or array) to an
87
+ * array, and flattens. A zcap query whose `capabilityQuery` is missing or not
88
+ * an object is malformed -- there is nothing to ask consent for -- so it throws
89
+ * rather than letting an `undefined` descriptor reach grant resolution;
90
+ * classification-time callers surface the throw as a malformed-request state.
91
+ *
92
+ * @param queries {IVPRQuery[]}
93
+ * @returns {ICapabilityQueryDetail[]}
94
+ */
95
+ export declare function zcapQueriesOf(queries: IVPRQuery[]): ICapabilityQueryDetail[];
96
+ /**
97
+ * Validates an App Connect `app.appUrl` against the attested requesting origin
98
+ * and returns its serialized form. The value must parse as an absolute URL,
99
+ * must not carry a fragment, and its origin must equal the attested origin;
100
+ * any violation throws (the query is malformed). All storage and comparison
101
+ * downstream uses the returned serialization, so spellings differing only in
102
+ * a default port, percent-encoding case, or dot-segments do not name distinct
103
+ * applications.
104
+ *
105
+ * The rule is the origin's, with no scheme constraint of its own: an `appUrl`
106
+ * under any scheme is accepted when its origin equals the attested one, which
107
+ * is what the App Connect spec asks. The one consequence of that is the
108
+ * opaque-origin refusal. A URL under a non-special scheme (`chrome-extension:`,
109
+ * `file:`, a custom scheme) has an opaque origin, which serializes as the
110
+ * string `"null"` and is same-origin only with itself, so two such strings
111
+ * being equal proves nothing; such an `appUrl` is refused as not same-origin
112
+ * rather than compared. The wallet-onboarding `host` validator is the
113
+ * mirror: it checks the scheme and no origin, since an exchange attests
114
+ * none.
115
+ *
116
+ * @param options {object}
117
+ * @param options.appUrl {string} - The request's `app.appUrl`.
118
+ * @param options.origin {string} - The attested requesting origin.
119
+ * @returns {string} The parsed URL's serialization.
120
+ */
121
+ export declare function serializedAppUrl({ appUrl, origin }: {
122
+ appUrl: string;
123
+ origin: string;
124
+ }): string;
125
+ /**
126
+ * Extracts the App Connect request from a query set, when one is present. An
127
+ * `AppConnectQuery` is one mental model per popup: the request must not also
128
+ * carry `QueryByExample` or standalone zcap queries, at most one
129
+ * `AppConnectQuery` is allowed, and its `app` block must carry the display
130
+ * `name` and the `appUrl` the wallet needs to match or mint the app-key
131
+ * credential -- with the `appUrl` validated against the attested requesting
132
+ * origin and rewritten to its serialized form ({@link serializedAppUrl}).
133
+ * Violations throw; classification-time callers surface the throw as a
134
+ * malformed-request state. The capability queries are normalized to an array
135
+ * (absent means "no grants requested" -- a connect that only recovers the app
136
+ * key is legal), and each entry is rebuilt from an allowlist of the declared
137
+ * fields (`referenceId`, `allowedAction`, `invocationTarget`): the type-level
138
+ * Omit does not bind an actual request body, so any other wire-level field --
139
+ * a smuggled `reason`, an attacker-chosen `controller`, a future
140
+ * display-bearing addition -- is made unrepresentable here, before the entries
141
+ * reach the profile the consent screen and the delegation path read.
142
+ *
143
+ * @param options {object}
144
+ * @param options.queries {IVPRQuery[]}
145
+ * @param options.origin {string} - The attested requesting origin the
146
+ * `appUrl` is validated against.
147
+ * @returns {IAppConnectRequest | null}
148
+ */
149
+ export declare function appConnectRequestOf({ queries, origin }: {
150
+ queries: IVPRQuery[];
151
+ origin: string;
152
+ }): IAppConnectRequest | null;
153
+ /**
154
+ * The longest self-declared agent name a request may carry, after trimming.
155
+ */
156
+ export declare const AGENT_NAME_MAX_LENGTH = 64;
157
+ /**
158
+ * Normalizes a self-declared agent name to the form the consent surface and
159
+ * the Login activity carry: trimmed, 1 to {@link AGENT_NAME_MAX_LENGTH}
160
+ * characters, with no control characters (C0 or C1, line breaks included).
161
+ * Any Unicode letter is fine -- names are not ASCII-only -- but a name that
162
+ * could spoof layout or sneak past a one-line render is refused. Both the
163
+ * requester side (`composeCapabilityRequest`) and the wallet side
164
+ * (`requestingAgentOf`) run this, so a name the requester could compose is
165
+ * one the wallet accepts.
166
+ *
167
+ * @param options {object}
168
+ * @param options.name {unknown} the raw `agent.name` value
169
+ * @returns {string} the trimmed name
170
+ */
171
+ export declare function normalizeAgentName({ name }: {
172
+ name: unknown;
173
+ }): string;
174
+ /**
175
+ * Reads the requester's self-declared identity off a VPR body, when present:
176
+ * the root `agent` member, whose `name` is validated and trimmed by
177
+ * {@link normalizeAgentName}. An absent member is fine (the wallet shows the
178
+ * grantee key alone); a present one that is not an object or whose name fails
179
+ * the limits is malformed and throws, so classification-time callers surface
180
+ * it as a malformed-request state rather than rendering an unbounded string.
181
+ *
182
+ * @param request {IVPRDetails}
183
+ * @returns {{ name: string } | undefined}
184
+ */
185
+ export declare function requestingAgentOf(request: IVPRDetails): {
186
+ name: string;
187
+ } | undefined;
188
+ /**
189
+ * Classifies a VPR body onto the independent axes the consent screen and
190
+ * response assembly work from: whether DID Authentication is requested, and
191
+ * separately the credential (`QueryByExample`) and capability
192
+ * (`AuthorizationCapabilityQuery` / `ZcapQuery`) content asked for, plus the
193
+ * requester's self-declared `agent` name when the body carries one. Any
194
+ * combination is valid, including zcap-only.
195
+ *
196
+ * @param request {IVPRDetails}
197
+ * @returns {WalletRequestProfile}
198
+ */
199
+ export declare function classifyRequest(request: IVPRDetails): WalletRequestProfile;
200
+ /**
201
+ * Whether a classified request is DID-Authentication *only*: it asks the wallet
202
+ * to prove control of its DID and nothing else (no credential queries, no
203
+ * capability requests). Derived from the profile so a popup's restore fast-path
204
+ * and its render both dispatch on the one predicate.
205
+ *
206
+ * @param profile {WalletRequestProfile}
207
+ * @returns {boolean}
208
+ */
209
+ export declare function isDidAuthOnly(profile: WalletRequestProfile): boolean;
210
+ /**
211
+ * The DID methods a caller can present a holder for, by bare method name, as
212
+ * `acceptedMethods` states them (`key`, `web`, `webvh`). The default is the
213
+ * one every wallet holds: a session with no promoted account presents its
214
+ * did:key and nothing else.
215
+ */
216
+ export declare const DEFAULT_PRESENTABLE_DID_METHODS: readonly ["key"];
217
+ /**
218
+ * Returns true if the caller can satisfy the DID method a `DIDAuthentication`
219
+ * query constrains to. `presentableMethods` names the bare DID method names
220
+ * this session can present a holder for; a request that omits
221
+ * `acceptedMethods` entirely, or lists it empty, imposes no constraint and is
222
+ * satisfiable whatever the session holds. A malformed `acceptedMethods` (not
223
+ * an array, or holding non-object entries) is read for the entries it does
224
+ * have rather than dereferenced blindly: an `acceptedMethods` that is not a
225
+ * list of constraints at all imposes none.
226
+ *
227
+ * @param queries {IVPRQuery[]}
228
+ * @param [presentableMethods] {readonly string[]} default
229
+ * {@link DEFAULT_PRESENTABLE_DID_METHODS}
230
+ * @returns {boolean}
231
+ */
232
+ export declare function didAuthMethodSupported(queries: IVPRQuery[], presentableMethods?: readonly string[]): boolean;
233
+ //# sourceMappingURL=classify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.d.ts","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EACV,eAAe,EAGf,kBAAkB,EAClB,sBAAsB,EACtB,gBAAgB,EAEhB,eAAe,EACf,QAAQ,EACR,UAAU,EACV,WAAW,EACX,SAAS,EACT,qBAAqB,EACrB,uBAAuB,EACvB,oBAAoB,EACrB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,OAAO,EAEL,WAAW,EAEZ,MAAM,sBAAsB,CAAA;AAE7B,OAAO,EAAE,WAAW,EAAE,CAAA;AAmBtB;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,qBAAqB,EAAE,GACnC,MAAM,CAOR;AA0DD;;;;;GAKG;AACH,wBAAgB,aAAa,CAC3B,YAAY,EAAE,uBAAuB,GACpC,qBAAqB,EAAE,CAQzB;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,aAAa,GAAG,UAAU,CAYtE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,eAAe,GAAG,QAAQ,CAKxE;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACR,EAAE;IACD,OAAO,EAAE,SAAS,EAAE,CAAA;CACrB,GAAG,OAAO,CAQV;AAED;;;;;;;;;GASG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,EAAE,CAS3D;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,eAAe,GACrB,gBAAgB,EAAE,CAMpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,EAAE,GAAG,sBAAsB,EAAE,CAc5E;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,MAAM,EACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,MAAM,CAqBT;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,MAAM,EACP,EAAE;IACD,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,MAAM,EAAE,MAAM,CAAA;CACf,GAAG,kBAAkB,GAAG,IAAI,CAmC5B;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,KAAK,CAAA;AAEvC;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,EAAE,IAAI,EAAE,EAAE;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GAAG,MAAM,CAoBtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,WAAW,GACnB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAS9B;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,WAAW,GAAG,oBAAoB,CAW1E;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,oBAAoB,GAAG,OAAO,CAMpE;AAED;;;;;GAKG;AACH,eAAO,MAAM,+BAA+B,kBAAmB,CAAA;AAE/D;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,sBAAsB,CACpC,OAAO,EAAE,SAAS,EAAE,EACpB,kBAAkB,GAAE,SAAS,MAAM,EAAoC,GACtE,OAAO,CAYT"}
@@ -0,0 +1,419 @@
1
+ import { typeArray } from '@interop/data-integrity-core/guards';
2
+ import { exclusiveQueryOf, isZcapQuery, parsedAbsoluteUrl } from './queryPredicates.js';
3
+ export { isZcapQuery };
4
+ const VC_1_CONTEXT_URL = 'https://www.w3.org/2018/credentials/v1';
5
+ const VC_2_CONTEXT_URL = 'https://www.w3.org/ns/credentials/v2';
6
+ /**
7
+ * Narrows an untrusted value to a string-keyed record, or `undefined` when it
8
+ * is not an object.
9
+ *
10
+ * @param value {unknown}
11
+ * @returns {Record<string, unknown> | undefined}
12
+ */
13
+ function asRecord(value) {
14
+ if (!value || typeof value !== 'object') {
15
+ return undefined;
16
+ }
17
+ return value;
18
+ }
19
+ /**
20
+ * The VC data model version a presentation carrying the given credentials must
21
+ * use, so its `@context` stays coherent with what it carries: `2.0` when any
22
+ * credential is a VC 2.0 one, else `1.0`. Shared by the bare-credential
23
+ * wrapping below and by the unsigned branch of `composeVp` (the signed branch
24
+ * takes its version from the negotiated cryptosuite instead).
25
+ *
26
+ * @param credentials {IVerifiableCredential[]}
27
+ * @returns {number}
28
+ */
29
+ export function presentationVersionFor(credentials) {
30
+ const isV2 = credentials.some(credential => {
31
+ const contexts = credential?.['@context'];
32
+ const contextArray = Array.isArray(contexts) ? contexts : [contexts];
33
+ return contextArray.includes(VC_2_CONTEXT_URL);
34
+ });
35
+ return isV2 ? 2.0 : 1.0;
36
+ }
37
+ /**
38
+ * Wraps a bare Verifiable Credential in an unsigned Verifiable Presentation,
39
+ * matching the credential's VC data model version so the presentation's
40
+ * `@context` stays coherent with the credential it carries.
41
+ *
42
+ * @param credential {IVerifiableCredential}
43
+ * @returns {IVerifiablePresentation}
44
+ */
45
+ function presentationWrapping(credential) {
46
+ const isV2 = presentationVersionFor([credential]) === 2.0;
47
+ return {
48
+ '@context': [isV2 ? VC_2_CONTEXT_URL : VC_1_CONTEXT_URL],
49
+ type: ['VerifiablePresentation'],
50
+ verifiableCredential: [credential]
51
+ };
52
+ }
53
+ /**
54
+ * The offered payload as a Verifiable Presentation: passed through when the
55
+ * issuer already offered one, and wrapped when it offered a bare Verifiable
56
+ * Credential. A `data` payload that is not an object at all is unrecognized,
57
+ * and reported with the same descriptive error as an unrecognized object.
58
+ *
59
+ * @param credential {CHAPIStoreEvent['credential']}
60
+ * @returns {IVerifiablePresentation}
61
+ */
62
+ function offeredPresentation({ dataType, data }) {
63
+ const payload = asRecord(data);
64
+ const types = typeArray(payload?.type);
65
+ const isPresentation = !!payload &&
66
+ (dataType === 'VerifiablePresentation' ||
67
+ types.includes('VerifiablePresentation') ||
68
+ 'verifiableCredential' in payload);
69
+ if (isPresentation) {
70
+ return data;
71
+ }
72
+ if (payload &&
73
+ (dataType === 'VerifiableCredential' ||
74
+ types.includes('VerifiableCredential'))) {
75
+ return presentationWrapping(data);
76
+ }
77
+ throw new Error(`CHAPI store event offered an unrecognized payload (dataType: ${dataType ?? 'undefined'}, type: ${JSON.stringify(types)}).`);
78
+ }
79
+ /**
80
+ * The Verifiable Credentials carried by a presentation, normalized to an array.
81
+ *
82
+ * @param presentation {IVerifiablePresentation}
83
+ * @returns {IVerifiableCredential[]}
84
+ */
85
+ export function credentialsOf(presentation) {
86
+ const { verifiableCredential } = presentation;
87
+ if (!verifiableCredential) {
88
+ return [];
89
+ }
90
+ return Array.isArray(verifiableCredential)
91
+ ? verifiableCredential
92
+ : [verifiableCredential];
93
+ }
94
+ /**
95
+ * Wraps a CHAPI get event as an `IVPRequest`.
96
+ *
97
+ * @param event {CHAPIGetEvent}
98
+ * @returns {IVPRequest}
99
+ */
100
+ export function classifyCHAPIGetEvent(event) {
101
+ const verifiablePresentationRequest = event.credentialRequestOptions?.web?.VerifiablePresentation;
102
+ if (!verifiablePresentationRequest) {
103
+ throw new Error('CHAPI get event is missing a VerifiablePresentation request.');
104
+ }
105
+ return {
106
+ verifiablePresentationRequest,
107
+ credentialRequestOrigin: event.credentialRequestOrigin
108
+ };
109
+ }
110
+ /**
111
+ * Wraps a CHAPI store event as an `IVPOffer`. A bare offered credential is
112
+ * wrapped in an unsigned presentation, so downstream code always sees a VP.
113
+ *
114
+ * @param event {CHAPIStoreEvent}
115
+ * @returns {IVPOffer}
116
+ */
117
+ export function classifyCHAPIStoreEvent(event) {
118
+ return {
119
+ verifiablePresentation: offeredPresentation(event.credential),
120
+ credentialRequestOrigin: event.credentialRequestOrigin
121
+ };
122
+ }
123
+ /**
124
+ * Returns true if the query set contains a `DIDAuthentication` query. Throws if
125
+ * more than one is present -- a single DID-Auth proof answers the request.
126
+ *
127
+ * @param options {object}
128
+ * @param options.queries {IVPRQuery[]}
129
+ * @returns {boolean}
130
+ */
131
+ export function isDIDAuthRequested({ queries }) {
132
+ const didAuthRequests = queries.filter(query => query.type === 'DIDAuthentication');
133
+ if (didAuthRequests.length > 1) {
134
+ throw new Error('More than one DIDAuthentication request found, exiting.');
135
+ }
136
+ return didAuthRequests.length === 1;
137
+ }
138
+ /**
139
+ * Normalizes a VPR's `query` (which may be a single object or an array) to an
140
+ * array, dropping anything that is not a typed query object. A VPR body can
141
+ * legitimately carry no queries at all -- a CHAPI request that names a
142
+ * `protocols` exchange sends an empty body -- so callers get an empty array
143
+ * rather than an array holding `undefined`.
144
+ *
145
+ * @param request {IVPRDetails}
146
+ * @returns {IVPRQuery[]}
147
+ */
148
+ export function queriesOf(request) {
149
+ const { query } = request;
150
+ const queries = Array.isArray(query) ? query : [query];
151
+ return queries.filter((entry) => !!entry &&
152
+ typeof entry === 'object' &&
153
+ typeof entry.type === 'string');
154
+ }
155
+ /**
156
+ * Normalizes a `QueryByExample`'s `credentialQuery` (a single detail object or
157
+ * an array of them) to an array.
158
+ *
159
+ * @param query {IQueryByExample}
160
+ * @returns {ICredentialQuery[]}
161
+ */
162
+ export function credentialQueriesOf(query) {
163
+ const { credentialQuery } = query;
164
+ if (!credentialQuery) {
165
+ return [];
166
+ }
167
+ return Array.isArray(credentialQuery) ? credentialQuery : [credentialQuery];
168
+ }
169
+ /**
170
+ * Collects the requested capabilities from a query set: filters the two zcap
171
+ * query type strings (`AuthorizationCapabilityQuery` canonical, `ZcapQuery`
172
+ * legacy alias), normalizes each `capabilityQuery` (object or array) to an
173
+ * array, and flattens. A zcap query whose `capabilityQuery` is missing or not
174
+ * an object is malformed -- there is nothing to ask consent for -- so it throws
175
+ * rather than letting an `undefined` descriptor reach grant resolution;
176
+ * classification-time callers surface the throw as a malformed-request state.
177
+ *
178
+ * @param queries {IVPRQuery[]}
179
+ * @returns {ICapabilityQueryDetail[]}
180
+ */
181
+ export function zcapQueriesOf(queries) {
182
+ return queries.filter(isZcapQuery).flatMap(({ type, capabilityQuery }) => {
183
+ const detailEntries = Array.isArray(capabilityQuery)
184
+ ? capabilityQuery
185
+ : [capabilityQuery];
186
+ for (const detail of detailEntries) {
187
+ if (!detail || typeof detail !== 'object') {
188
+ throw new Error(`A "${type}" query is missing its capabilityQuery detail.`);
189
+ }
190
+ }
191
+ return detailEntries;
192
+ });
193
+ }
194
+ /**
195
+ * Validates an App Connect `app.appUrl` against the attested requesting origin
196
+ * and returns its serialized form. The value must parse as an absolute URL,
197
+ * must not carry a fragment, and its origin must equal the attested origin;
198
+ * any violation throws (the query is malformed). All storage and comparison
199
+ * downstream uses the returned serialization, so spellings differing only in
200
+ * a default port, percent-encoding case, or dot-segments do not name distinct
201
+ * applications.
202
+ *
203
+ * The rule is the origin's, with no scheme constraint of its own: an `appUrl`
204
+ * under any scheme is accepted when its origin equals the attested one, which
205
+ * is what the App Connect spec asks. The one consequence of that is the
206
+ * opaque-origin refusal. A URL under a non-special scheme (`chrome-extension:`,
207
+ * `file:`, a custom scheme) has an opaque origin, which serializes as the
208
+ * string `"null"` and is same-origin only with itself, so two such strings
209
+ * being equal proves nothing; such an `appUrl` is refused as not same-origin
210
+ * rather than compared. The wallet-onboarding `host` validator is the
211
+ * mirror: it checks the scheme and no origin, since an exchange attests
212
+ * none.
213
+ *
214
+ * @param options {object}
215
+ * @param options.appUrl {string} - The request's `app.appUrl`.
216
+ * @param options.origin {string} - The attested requesting origin.
217
+ * @returns {string} The parsed URL's serialization.
218
+ */
219
+ export function serializedAppUrl({ appUrl, origin }) {
220
+ const url = parsedAbsoluteUrl({
221
+ value: appUrl,
222
+ notAbsoluteMessage: `An AppConnectQuery "appUrl" must be an absolute URL (got "${appUrl}").`,
223
+ fragmentMessage: `An AppConnectQuery "appUrl" must not carry a fragment (got "${appUrl}").`
224
+ });
225
+ let attestedOrigin;
226
+ try {
227
+ attestedOrigin = new URL(origin).origin;
228
+ }
229
+ catch {
230
+ attestedOrigin = origin;
231
+ }
232
+ // An opaque origin serializes as the string "null" and is same-origin with
233
+ // nothing but itself, so an equal pair of "null" strings proves nothing.
234
+ if (url.origin === 'null' || url.origin !== attestedOrigin) {
235
+ throw new Error(`An AppConnectQuery "appUrl" must be same-origin with the requesting ` +
236
+ `origin "${origin}" (got "${appUrl}").`);
237
+ }
238
+ return url.href;
239
+ }
240
+ /**
241
+ * Extracts the App Connect request from a query set, when one is present. An
242
+ * `AppConnectQuery` is one mental model per popup: the request must not also
243
+ * carry `QueryByExample` or standalone zcap queries, at most one
244
+ * `AppConnectQuery` is allowed, and its `app` block must carry the display
245
+ * `name` and the `appUrl` the wallet needs to match or mint the app-key
246
+ * credential -- with the `appUrl` validated against the attested requesting
247
+ * origin and rewritten to its serialized form ({@link serializedAppUrl}).
248
+ * Violations throw; classification-time callers surface the throw as a
249
+ * malformed-request state. The capability queries are normalized to an array
250
+ * (absent means "no grants requested" -- a connect that only recovers the app
251
+ * key is legal), and each entry is rebuilt from an allowlist of the declared
252
+ * fields (`referenceId`, `allowedAction`, `invocationTarget`): the type-level
253
+ * Omit does not bind an actual request body, so any other wire-level field --
254
+ * a smuggled `reason`, an attacker-chosen `controller`, a future
255
+ * display-bearing addition -- is made unrepresentable here, before the entries
256
+ * reach the profile the consent screen and the delegation path read.
257
+ *
258
+ * @param options {object}
259
+ * @param options.queries {IVPRQuery[]}
260
+ * @param options.origin {string} - The attested requesting origin the
261
+ * `appUrl` is validated against.
262
+ * @returns {IAppConnectRequest | null}
263
+ */
264
+ export function appConnectRequestOf({ queries, origin }) {
265
+ const appConnectQuery = exclusiveQueryOf({
266
+ queries,
267
+ typeName: 'AppConnectQuery'
268
+ });
269
+ if (appConnectQuery === null) {
270
+ return null;
271
+ }
272
+ const { app, capabilityQuery } = appConnectQuery;
273
+ if (!app || typeof app.name !== 'string' || typeof app.appUrl !== 'string') {
274
+ throw new Error('An AppConnectQuery is missing its app name / appUrl.');
275
+ }
276
+ const appUrl = serializedAppUrl({ appUrl: app.appUrl, origin });
277
+ const rawQueries = capabilityQuery === undefined
278
+ ? []
279
+ : Array.isArray(capabilityQuery)
280
+ ? capabilityQuery
281
+ : [capabilityQuery];
282
+ const capabilityQueries = rawQueries.map(detail => {
283
+ if (!detail || typeof detail !== 'object') {
284
+ throw new Error('An AppConnectQuery carries a malformed capabilityQuery entry.');
285
+ }
286
+ const { referenceId, allowedAction, invocationTarget } = detail;
287
+ return {
288
+ ...(referenceId !== undefined && { referenceId }),
289
+ ...(allowedAction !== undefined && { allowedAction }),
290
+ invocationTarget
291
+ };
292
+ });
293
+ return { app: { name: app.name, appUrl }, capabilityQueries };
294
+ }
295
+ /**
296
+ * The longest self-declared agent name a request may carry, after trimming.
297
+ */
298
+ export const AGENT_NAME_MAX_LENGTH = 64;
299
+ /**
300
+ * Normalizes a self-declared agent name to the form the consent surface and
301
+ * the Login activity carry: trimmed, 1 to {@link AGENT_NAME_MAX_LENGTH}
302
+ * characters, with no control characters (C0 or C1, line breaks included).
303
+ * Any Unicode letter is fine -- names are not ASCII-only -- but a name that
304
+ * could spoof layout or sneak past a one-line render is refused. Both the
305
+ * requester side (`composeCapabilityRequest`) and the wallet side
306
+ * (`requestingAgentOf`) run this, so a name the requester could compose is
307
+ * one the wallet accepts.
308
+ *
309
+ * @param options {object}
310
+ * @param options.name {unknown} the raw `agent.name` value
311
+ * @returns {string} the trimmed name
312
+ */
313
+ export function normalizeAgentName({ name }) {
314
+ if (typeof name !== 'string') {
315
+ throw new Error('A request\'s "agent.name" must be a string.');
316
+ }
317
+ const trimmed = name.trim();
318
+ if (trimmed.length === 0) {
319
+ throw new Error('A request\'s "agent.name" must not be empty.');
320
+ }
321
+ if (trimmed.length > AGENT_NAME_MAX_LENGTH) {
322
+ throw new Error(`A request's "agent.name" must be at most ${AGENT_NAME_MAX_LENGTH} ` +
323
+ `characters (got ${trimmed.length}).`);
324
+ }
325
+ if (/\p{Cc}/u.test(trimmed)) {
326
+ throw new Error('A request\'s "agent.name" must not contain control characters.');
327
+ }
328
+ return trimmed;
329
+ }
330
+ /**
331
+ * Reads the requester's self-declared identity off a VPR body, when present:
332
+ * the root `agent` member, whose `name` is validated and trimmed by
333
+ * {@link normalizeAgentName}. An absent member is fine (the wallet shows the
334
+ * grantee key alone); a present one that is not an object or whose name fails
335
+ * the limits is malformed and throws, so classification-time callers surface
336
+ * it as a malformed-request state rather than rendering an unbounded string.
337
+ *
338
+ * @param request {IVPRDetails}
339
+ * @returns {{ name: string } | undefined}
340
+ */
341
+ export function requestingAgentOf(request) {
342
+ const { agent } = request;
343
+ if (agent === undefined) {
344
+ return undefined;
345
+ }
346
+ if (!agent || typeof agent !== 'object' || Array.isArray(agent)) {
347
+ throw new Error('A request\'s "agent" member must be an object.');
348
+ }
349
+ return { name: normalizeAgentName({ name: agent.name }) };
350
+ }
351
+ /**
352
+ * Classifies a VPR body onto the independent axes the consent screen and
353
+ * response assembly work from: whether DID Authentication is requested, and
354
+ * separately the credential (`QueryByExample`) and capability
355
+ * (`AuthorizationCapabilityQuery` / `ZcapQuery`) content asked for, plus the
356
+ * requester's self-declared `agent` name when the body carries one. Any
357
+ * combination is valid, including zcap-only.
358
+ *
359
+ * @param request {IVPRDetails}
360
+ * @returns {WalletRequestProfile}
361
+ */
362
+ export function classifyRequest(request) {
363
+ const queries = queriesOf(request);
364
+ const agent = requestingAgentOf(request);
365
+ return {
366
+ didAuth: isDIDAuthRequested({ queries }),
367
+ vcQueries: queries.filter((query) => query.type === 'QueryByExample'),
368
+ zcapRequests: zcapQueriesOf(queries),
369
+ ...(agent !== undefined && { agent })
370
+ };
371
+ }
372
+ /**
373
+ * Whether a classified request is DID-Authentication *only*: it asks the wallet
374
+ * to prove control of its DID and nothing else (no credential queries, no
375
+ * capability requests). Derived from the profile so a popup's restore fast-path
376
+ * and its render both dispatch on the one predicate.
377
+ *
378
+ * @param profile {WalletRequestProfile}
379
+ * @returns {boolean}
380
+ */
381
+ export function isDidAuthOnly(profile) {
382
+ return (profile.didAuth &&
383
+ profile.vcQueries.length === 0 &&
384
+ profile.zcapRequests.length === 0);
385
+ }
386
+ /**
387
+ * The DID methods a caller can present a holder for, by bare method name, as
388
+ * `acceptedMethods` states them (`key`, `web`, `webvh`). The default is the
389
+ * one every wallet holds: a session with no promoted account presents its
390
+ * did:key and nothing else.
391
+ */
392
+ export const DEFAULT_PRESENTABLE_DID_METHODS = ['key'];
393
+ /**
394
+ * Returns true if the caller can satisfy the DID method a `DIDAuthentication`
395
+ * query constrains to. `presentableMethods` names the bare DID method names
396
+ * this session can present a holder for; a request that omits
397
+ * `acceptedMethods` entirely, or lists it empty, imposes no constraint and is
398
+ * satisfiable whatever the session holds. A malformed `acceptedMethods` (not
399
+ * an array, or holding non-object entries) is read for the entries it does
400
+ * have rather than dereferenced blindly: an `acceptedMethods` that is not a
401
+ * list of constraints at all imposes none.
402
+ *
403
+ * @param queries {IVPRQuery[]}
404
+ * @param [presentableMethods] {readonly string[]} default
405
+ * {@link DEFAULT_PRESENTABLE_DID_METHODS}
406
+ * @returns {boolean}
407
+ */
408
+ export function didAuthMethodSupported(queries, presentableMethods = DEFAULT_PRESENTABLE_DID_METHODS) {
409
+ const didAuth = queries.find(query => query.type === 'DIDAuthentication');
410
+ const acceptedMethods = didAuth?.acceptedMethods;
411
+ if (!Array.isArray(acceptedMethods) || acceptedMethods.length === 0) {
412
+ return true;
413
+ }
414
+ return acceptedMethods.some(entry => {
415
+ const method = asRecord(entry)?.method;
416
+ return typeof method === 'string' && presentableMethods.includes(method);
417
+ });
418
+ }
419
+ //# sourceMappingURL=classify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"classify.js","sourceRoot":"","sources":["../src/classify.ts"],"names":[],"mappings":"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"}