@interop/wallet-core 0.23.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +33 -18
- package/dist/clients/revocation.d.ts +3 -6
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +5 -9
- package/dist/clients/revocation.js.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +11 -17
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.js +22 -27
- package/dist/clients/rosterPolicy.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts +2 -2
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +15 -10
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/keys/index.d.ts +11 -8
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +11 -8
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/rosterLogStore.d.ts +34 -0
- package/dist/keys/rosterLogStore.d.ts.map +1 -0
- package/dist/keys/rosterLogStore.js +110 -0
- package/dist/keys/rosterLogStore.js.map +1 -0
- package/dist/keys/rosterStore.d.ts +18 -4
- package/dist/keys/rosterStore.d.ts.map +1 -1
- package/dist/keys/rosterStore.js +35 -16
- package/dist/keys/rosterStore.js.map +1 -1
- package/dist/keys/userKeyCascade.d.ts +1 -1
- package/dist/keys/userKeyCascade.js +1 -1
- package/dist/keys/userKeyRoster.d.ts +50 -97
- package/dist/keys/userKeyRoster.d.ts.map +1 -1
- package/dist/keys/userKeyRoster.js +44 -145
- package/dist/keys/userKeyRoster.js.map +1 -1
- package/dist/request/appKey.d.ts +254 -0
- package/dist/request/appKey.d.ts.map +1 -0
- package/dist/request/appKey.js +498 -0
- package/dist/request/appKey.js.map +1 -0
- package/dist/request/classify.d.ts +54 -3
- package/dist/request/classify.d.ts.map +1 -1
- package/dist/request/classify.js +106 -0
- package/dist/request/classify.js.map +1 -1
- package/dist/request/index.d.ts +4 -0
- package/dist/request/index.d.ts.map +1 -1
- package/dist/request/index.js +4 -0
- package/dist/request/index.js.map +1 -1
- package/dist/request/processRequest.d.ts.map +1 -1
- package/dist/request/processRequest.js +15 -6
- package/dist/request/processRequest.js.map +1 -1
- package/dist/request/types.d.ts +45 -2
- package/dist/request/types.d.ts.map +1 -1
- package/dist/resourceLog/append.d.ts +103 -0
- package/dist/resourceLog/append.d.ts.map +1 -0
- package/dist/resourceLog/append.js +190 -0
- package/dist/resourceLog/append.js.map +1 -0
- package/dist/resourceLog/controller.d.ts +57 -0
- package/dist/resourceLog/controller.d.ts.map +1 -0
- package/dist/resourceLog/controller.js +81 -0
- package/dist/resourceLog/controller.js.map +1 -0
- package/dist/resourceLog/entry.d.ts +68 -0
- package/dist/resourceLog/entry.d.ts.map +1 -0
- package/dist/resourceLog/entry.js +167 -0
- package/dist/resourceLog/entry.js.map +1 -0
- package/dist/resourceLog/errors.d.ts +75 -0
- package/dist/resourceLog/errors.d.ts.map +1 -0
- package/dist/resourceLog/errors.js +76 -0
- package/dist/resourceLog/errors.js.map +1 -0
- package/dist/resourceLog/index.d.ts +23 -0
- package/dist/resourceLog/index.d.ts.map +1 -0
- package/dist/resourceLog/index.js +23 -0
- package/dist/resourceLog/index.js.map +1 -0
- package/dist/resourceLog/pin.d.ts +44 -0
- package/dist/resourceLog/pin.d.ts.map +1 -0
- package/dist/resourceLog/pin.js +32 -0
- package/dist/resourceLog/pin.js.map +1 -0
- package/dist/resourceLog/verify.d.ts +89 -0
- package/dist/resourceLog/verify.d.ts.map +1 -0
- package/dist/resourceLog/verify.js +434 -0
- package/dist/resourceLog/verify.js.map +1 -0
- package/dist/space/collections.d.ts +14 -11
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +14 -11
- package/dist/space/collections.js.map +1 -1
- package/dist/space/index.d.ts +2 -2
- package/dist/space/index.d.ts.map +1 -1
- package/dist/space/index.js +2 -2
- package/dist/space/index.js.map +1 -1
- package/dist/webvh/didWeb.d.ts +4 -6
- package/dist/webvh/didWeb.d.ts.map +1 -1
- package/dist/webvh/didWeb.js.map +1 -1
- package/dist/webvh/didWebvh.d.ts +1 -2
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +1 -6
- package/dist/webvh/didWebvh.js.map +1 -1
- package/package.json +10 -4
package/dist/request/classify.js
CHANGED
|
@@ -180,6 +180,112 @@ export function zcapQueriesOf(queries) {
|
|
|
180
180
|
return detailEntries;
|
|
181
181
|
});
|
|
182
182
|
}
|
|
183
|
+
/**
|
|
184
|
+
* Validates an App Connect `app.appUrl` against the attested requesting origin
|
|
185
|
+
* and returns its serialized form. The value must parse as an absolute URL,
|
|
186
|
+
* must not carry a fragment, and its origin must equal the attested origin;
|
|
187
|
+
* any violation throws (the query is malformed). All storage and comparison
|
|
188
|
+
* downstream uses the returned serialization, so spellings differing only in
|
|
189
|
+
* a default port, percent-encoding case, or dot-segments do not name distinct
|
|
190
|
+
* applications.
|
|
191
|
+
*
|
|
192
|
+
* The fragment check reads the serialized URL rather than `url.hash`: a bare
|
|
193
|
+
* trailing `#` sets an empty (non-null) fragment that `hash` reports as `''`,
|
|
194
|
+
* and a percent-encoded `%23` never appears as `#` in the serialization.
|
|
195
|
+
*
|
|
196
|
+
* @param options {object}
|
|
197
|
+
* @param options.appUrl {string} - The request's `app.appUrl`.
|
|
198
|
+
* @param options.origin {string} - The attested requesting origin.
|
|
199
|
+
* @returns {string} The parsed URL's serialization.
|
|
200
|
+
*/
|
|
201
|
+
export function serializedAppUrl({ appUrl, origin }) {
|
|
202
|
+
let url;
|
|
203
|
+
try {
|
|
204
|
+
url = new URL(appUrl);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
throw new Error(`An AppConnectQuery "appUrl" must be an absolute URL (got "${appUrl}").`, { cause: err });
|
|
208
|
+
}
|
|
209
|
+
if (url.href.includes('#')) {
|
|
210
|
+
throw new Error(`An AppConnectQuery "appUrl" must not carry a fragment (got "${appUrl}").`);
|
|
211
|
+
}
|
|
212
|
+
let attestedOrigin;
|
|
213
|
+
try {
|
|
214
|
+
attestedOrigin = new URL(origin).origin;
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
attestedOrigin = origin;
|
|
218
|
+
}
|
|
219
|
+
if (url.origin !== attestedOrigin) {
|
|
220
|
+
throw new Error(`An AppConnectQuery "appUrl" must be same-origin with the requesting ` +
|
|
221
|
+
`origin "${origin}" (got "${appUrl}").`);
|
|
222
|
+
}
|
|
223
|
+
return url.href;
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Extracts the App Connect request from a query set, when one is present. An
|
|
227
|
+
* `AppConnectQuery` is one mental model per popup: the request must not also
|
|
228
|
+
* carry `QueryByExample` or standalone zcap queries, at most one
|
|
229
|
+
* `AppConnectQuery` is allowed, and its `app` block must carry the display
|
|
230
|
+
* `name` and the `appUrl` the wallet needs to match or mint the app-key
|
|
231
|
+
* credential -- with the `appUrl` validated against the attested requesting
|
|
232
|
+
* origin and rewritten to its serialized form ({@link serializedAppUrl}).
|
|
233
|
+
* Violations throw; classification-time callers surface the throw as a
|
|
234
|
+
* malformed-request state. The capability queries are normalized to an array
|
|
235
|
+
* (absent means "no grants requested" -- a connect that only recovers the app
|
|
236
|
+
* key is legal), and each entry is rebuilt from an allowlist of the declared
|
|
237
|
+
* fields (`referenceId`, `allowedAction`, `invocationTarget`): the type-level
|
|
238
|
+
* Omit does not bind an actual request body, so any other wire-level field --
|
|
239
|
+
* a smuggled `reason`, an attacker-chosen `controller`, a future
|
|
240
|
+
* display-bearing addition -- is made unrepresentable here, before the entries
|
|
241
|
+
* reach the profile the consent screen and the delegation path read.
|
|
242
|
+
*
|
|
243
|
+
* @param options {object}
|
|
244
|
+
* @param options.queries {IVPRQuery[]}
|
|
245
|
+
* @param options.origin {string} - The attested requesting origin the
|
|
246
|
+
* `appUrl` is validated against.
|
|
247
|
+
* @returns {IAppConnectRequest | null}
|
|
248
|
+
*/
|
|
249
|
+
export function appConnectRequestOf({ queries, origin }) {
|
|
250
|
+
// `AppConnectQuery` extends the spec query union, so it is matched by its
|
|
251
|
+
// `type` string and upcast rather than narrowed via a type predicate.
|
|
252
|
+
const appConnectQueries = queries.filter(query => query.type === 'AppConnectQuery');
|
|
253
|
+
if (appConnectQueries.length === 0) {
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
if (appConnectQueries.length > 1) {
|
|
257
|
+
throw new Error('More than one AppConnectQuery found, exiting.');
|
|
258
|
+
}
|
|
259
|
+
const mixed = queries.some(query => query.type === 'QueryByExample' ||
|
|
260
|
+
query.type === 'AuthorizationCapabilityQuery' ||
|
|
261
|
+
query.type === 'ZcapQuery');
|
|
262
|
+
if (mixed) {
|
|
263
|
+
throw new Error('An AppConnectQuery cannot be combined with QueryByExample or ' +
|
|
264
|
+
'standalone capability queries.');
|
|
265
|
+
}
|
|
266
|
+
const { app, capabilityQuery } = appConnectQueries[0];
|
|
267
|
+
if (!app || typeof app.name !== 'string' || typeof app.appUrl !== 'string') {
|
|
268
|
+
throw new Error('An AppConnectQuery is missing its app name / appUrl.');
|
|
269
|
+
}
|
|
270
|
+
const appUrl = serializedAppUrl({ appUrl: app.appUrl, origin });
|
|
271
|
+
const rawQueries = capabilityQuery === undefined
|
|
272
|
+
? []
|
|
273
|
+
: Array.isArray(capabilityQuery)
|
|
274
|
+
? capabilityQuery
|
|
275
|
+
: [capabilityQuery];
|
|
276
|
+
const capabilityQueries = rawQueries.map(detail => {
|
|
277
|
+
if (!detail || typeof detail !== 'object') {
|
|
278
|
+
throw new Error('An AppConnectQuery carries a malformed capabilityQuery entry.');
|
|
279
|
+
}
|
|
280
|
+
const { referenceId, allowedAction, invocationTarget } = detail;
|
|
281
|
+
return {
|
|
282
|
+
...(referenceId !== undefined && { referenceId }),
|
|
283
|
+
...(allowedAction !== undefined && { allowedAction }),
|
|
284
|
+
invocationTarget
|
|
285
|
+
};
|
|
286
|
+
});
|
|
287
|
+
return { app: { name: app.name, appUrl }, capabilityQueries };
|
|
288
|
+
}
|
|
183
289
|
/**
|
|
184
290
|
* Classifies a VPR body onto the independent axes the consent screen and
|
|
185
291
|
* response assembly work from: whether DID Authentication is requested, and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/request/classify.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"classify.js","sourceRoot":"","sources":["../../src/request/classify.ts"],"names":[],"mappings":"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"}
|
package/dist/request/index.d.ts
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* typed message and dispatch on what it asks for.
|
|
14
14
|
* - `matching` filters stored credentials against a QueryByExample (both the
|
|
15
15
|
* jsonpath deep matcher and the type/issuer matcher).
|
|
16
|
+
* - `appKey` is the App Connect app-key credential module: the wire constants,
|
|
17
|
+
* the matching / minting / legacy re-issue paths, and the store-time
|
|
18
|
+
* refusal policy.
|
|
16
19
|
* - `presentationSuite` negotiates the response cryptosuite; `composeVp` builds
|
|
17
20
|
* the (optionally signed, optionally grant-embedding) response VP.
|
|
18
21
|
* - `exchangeClient` is the fetch-injectable VC-API exchange client;
|
|
@@ -30,6 +33,7 @@ export * from './types.js';
|
|
|
30
33
|
export * from './parse.js';
|
|
31
34
|
export * from './classify.js';
|
|
32
35
|
export * from './matching.js';
|
|
36
|
+
export * from './appKey.js';
|
|
33
37
|
export * from './presentationSuite.js';
|
|
34
38
|
export * from './composeVp.js';
|
|
35
39
|
export * from './exchangeClient.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA"}
|
package/dist/request/index.js
CHANGED
|
@@ -13,6 +13,9 @@
|
|
|
13
13
|
* typed message and dispatch on what it asks for.
|
|
14
14
|
* - `matching` filters stored credentials against a QueryByExample (both the
|
|
15
15
|
* jsonpath deep matcher and the type/issuer matcher).
|
|
16
|
+
* - `appKey` is the App Connect app-key credential module: the wire constants,
|
|
17
|
+
* the matching / minting / legacy re-issue paths, and the store-time
|
|
18
|
+
* refusal policy.
|
|
16
19
|
* - `presentationSuite` negotiates the response cryptosuite; `composeVp` builds
|
|
17
20
|
* the (optionally signed, optionally grant-embedding) response VP.
|
|
18
21
|
* - `exchangeClient` is the fetch-injectable VC-API exchange client;
|
|
@@ -30,6 +33,7 @@ export * from './types.js';
|
|
|
30
33
|
export * from './parse.js';
|
|
31
34
|
export * from './classify.js';
|
|
32
35
|
export * from './matching.js';
|
|
36
|
+
export * from './appKey.js';
|
|
33
37
|
export * from './presentationSuite.js';
|
|
34
38
|
export * from './composeVp.js';
|
|
35
39
|
export * from './exchangeClient.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/request/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,eAAe,CAAA;AAC7B,cAAc,eAAe,CAAA;AAC7B,cAAc,aAAa,CAAA;AAC3B,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processRequest.d.ts","sourceRoot":"","sources":["../../src/request/processRequest.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,qBAAqB,EACrB,WAAW,EAEX,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAA;AAkBnB;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAOV;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,cAAc,CAAC,EACnC,OAAO,EACP,kBAAkB,EAClB,WAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,YAAY,EACb,EAAE;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,OAAO,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"processRequest.d.ts","sourceRoot":"","sources":["../../src/request/processRequest.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,qBAAqB,EACrB,WAAW,EAEX,kBAAkB,EAClB,iBAAiB,EACjB,cAAc,EACf,MAAM,YAAY,CAAA;AAkBnB;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACP,EAAE;IACD,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,GAAG,OAAO,CAOV;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,cAAc,CAAC,EACnC,OAAO,EACP,kBAAkB,EAClB,WAAgB,EAChB,uBAAuB,EACvB,UAAU,EACV,WAAW,EACX,YAAY,EACb,EAAE;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,kBAAkB,EAAE,kBAAkB,CAAA;IACtC,WAAW,CAAC,EAAE,qBAAqB,EAAE,CAAA;IACrC,uBAAuB,CAAC,EAAE,MAAM,CAAA;IAChC,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,OAAO,CAAC,cAAc,CAAC,CAmF1B"}
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* imported, so this layer carries no session / grant-resolution machinery. The
|
|
16
16
|
* signer and holder DID are injected as a {@link PresentationSigner}.
|
|
17
17
|
*/
|
|
18
|
-
import { classifyRequest, queriesOf } from './classify.js';
|
|
18
|
+
import { appConnectRequestOf, classifyRequest, queriesOf } from './classify.js';
|
|
19
19
|
import { composeVp } from './composeVp.js';
|
|
20
20
|
import { negotiateCryptosuite } from './presentationSuite.js';
|
|
21
21
|
/**
|
|
@@ -90,11 +90,12 @@ export async function processRequest({ request, presentationSigner, selectedVCs
|
|
|
90
90
|
throw new Error(`DID Auth domain "${domain}" does not match request origin ` +
|
|
91
91
|
`"${credentialRequestOrigin}".`);
|
|
92
92
|
}
|
|
93
|
-
// An App Connect request
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
//
|
|
97
|
-
//
|
|
93
|
+
// An App Connect request takes its own single-round branch, handled by the
|
|
94
|
+
// injected processor. The requesting origin is what the app key is bound to
|
|
95
|
+
// (and what the query's `appUrl` is validated against), so it is required;
|
|
96
|
+
// the query itself is validated here (`appConnectRequestOf` throws on a
|
|
97
|
+
// malformed `app` block), so the processor only ever sees a well-formed
|
|
98
|
+
// request whose `appUrl` is already in serialized form.
|
|
98
99
|
const appConnectRequested = queries.some(query => query.type === 'AppConnectQuery');
|
|
99
100
|
if (appConnectRequested) {
|
|
100
101
|
if (!processors?.processAppConnect) {
|
|
@@ -104,8 +105,16 @@ export async function processRequest({ request, presentationSigner, selectedVCs
|
|
|
104
105
|
if (!credentialRequestOrigin) {
|
|
105
106
|
throw new Error('An App Connect request requires a requesting origin.');
|
|
106
107
|
}
|
|
108
|
+
const appConnect = appConnectRequestOf({
|
|
109
|
+
queries,
|
|
110
|
+
origin: credentialRequestOrigin
|
|
111
|
+
});
|
|
112
|
+
if (!appConnect) {
|
|
113
|
+
throw new Error('An AppConnectQuery could not be classified.');
|
|
114
|
+
}
|
|
107
115
|
return processors.processAppConnect({
|
|
108
116
|
request,
|
|
117
|
+
appConnect,
|
|
109
118
|
origin: credentialRequestOrigin,
|
|
110
119
|
challenge,
|
|
111
120
|
domain,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"processRequest.js","sourceRoot":"","sources":["../../src/request/processRequest.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"processRequest.js","sourceRoot":"","sources":["../../src/request/processRequest.ts"],"names":[],"mappings":"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"}
|
package/dist/request/types.d.ts
CHANGED
|
@@ -105,6 +105,46 @@ export interface WalletRequestProfile {
|
|
|
105
105
|
vcQueries: IQueryByExample[];
|
|
106
106
|
zcapRequests: ICapabilityQueryDetail[];
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* A capability request entry as an `AppConnectQuery` carries it: the standard
|
|
110
|
+
* capability-query detail minus the members the wallet itself fills or refuses
|
|
111
|
+
* (`controller` is filled with the app-key subject DID at delegation time;
|
|
112
|
+
* `reason` is display-bearing and not accepted from an App Connect request).
|
|
113
|
+
*/
|
|
114
|
+
export type IAppConnectCapabilityQuery = Omit<ICapabilityQueryDetail, 'controller' | 'reason'>;
|
|
115
|
+
/**
|
|
116
|
+
* The app identity an App Connect request presents: a display `name` for the
|
|
117
|
+
* consent surface (attacker-controlled free text, never evidence of identity)
|
|
118
|
+
* and the application's canonical `appUrl`, which scopes the app-key identity
|
|
119
|
+
* within the requesting origin. Validated by `appConnectRequestOf`: the
|
|
120
|
+
* `appUrl` must parse as an absolute URL, carry no fragment, and be
|
|
121
|
+
* same-origin with the attested requesting origin.
|
|
122
|
+
*/
|
|
123
|
+
export type IAppConnectApp = {
|
|
124
|
+
name: string;
|
|
125
|
+
appUrl: string;
|
|
126
|
+
};
|
|
127
|
+
/**
|
|
128
|
+
* "Connect this app to the user's wallet and Space" -- a single-round request
|
|
129
|
+
* that combines app-key recovery-or-minting with capability delegation. The
|
|
130
|
+
* wallet finds (or self-issues) the app-key credential for the requesting
|
|
131
|
+
* origin and `appUrl`, delegates the requested capabilities to its subject
|
|
132
|
+
* DID, and returns credential + grants in one signed presentation.
|
|
133
|
+
*/
|
|
134
|
+
export type IAppConnectQuery = {
|
|
135
|
+
type: 'AppConnectQuery';
|
|
136
|
+
app: IAppConnectApp;
|
|
137
|
+
capabilityQuery?: IAppConnectCapabilityQuery | IAppConnectCapabilityQuery[];
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* An App Connect request as classified and validated by
|
|
141
|
+
* `appConnectRequestOf`: the app identity (its `appUrl` already in serialized
|
|
142
|
+
* form) plus its capability queries normalized to an array.
|
|
143
|
+
*/
|
|
144
|
+
export type IAppConnectRequest = {
|
|
145
|
+
app: IAppConnectApp;
|
|
146
|
+
capabilityQueries: IAppConnectCapabilityQuery[];
|
|
147
|
+
};
|
|
108
148
|
/**
|
|
109
149
|
* The authentication signer plus the DID to name as the VP `holder`. Each app
|
|
110
150
|
* resolves this from its own key material (DCW from the selected profile's
|
|
@@ -135,11 +175,14 @@ export interface RequestProcessors {
|
|
|
135
175
|
zcapRequests: ICapabilityQueryDetail[];
|
|
136
176
|
}) => Promise<IZcap[]>;
|
|
137
177
|
/**
|
|
138
|
-
* Handles the App Connect single-round branch
|
|
139
|
-
*
|
|
178
|
+
* Handles the App Connect single-round branch. Invoked when the request
|
|
179
|
+
* carries an `AppConnectQuery`; `appConnect` arrives already validated by
|
|
180
|
+
* `appConnectRequestOf` (its `app.appUrl` in serialized form), so the
|
|
181
|
+
* processor never sees a malformed app block.
|
|
140
182
|
*/
|
|
141
183
|
processAppConnect?: (args: {
|
|
142
184
|
request: IVPRDetails;
|
|
185
|
+
appConnect: IAppConnectRequest;
|
|
143
186
|
origin: string;
|
|
144
187
|
challenge?: string;
|
|
145
188
|
domain?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/request/types.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/request/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { type ResourceLogEntry, type ResourceLogStore } from '@interop/was-client/log';
|
|
2
|
+
import type { ResourceLogController } from './controller.js';
|
|
3
|
+
import { type ResourceLogSigner } from './entry.js';
|
|
4
|
+
import type { ResourceLogPinStore } from './pin.js';
|
|
5
|
+
import { type VerifiedResourceLog } from './verify.js';
|
|
6
|
+
/**
|
|
7
|
+
* Reads and fully verifies a log through the store seam, advancing the
|
|
8
|
+
* chain-head pin. Resolves `null` when the log resource does not exist yet
|
|
9
|
+
* (the pre-genesis state). The one read entry point every consumer -- a
|
|
10
|
+
* login-time roster read, a pre-append verification, a first-contact
|
|
11
|
+
* bootstrap -- goes through, so the pin rules cannot be bypassed by reading
|
|
12
|
+
* around them.
|
|
13
|
+
*
|
|
14
|
+
* @param options {object}
|
|
15
|
+
* @param options.store {ResourceLogStore} the log's transport seam
|
|
16
|
+
* @param options.controller {ResourceLogController} the verified controller
|
|
17
|
+
* view
|
|
18
|
+
* @param options.expectedMethod {string} the format identifier expected
|
|
19
|
+
* (also confirming any `history` dispatch hint the caller followed)
|
|
20
|
+
* @param options.pinStore {ResourceLogPinStore} this client's pin for this
|
|
21
|
+
* log
|
|
22
|
+
* @returns {Promise<{ verified: VerifiedResourceLog; etag?: string } | null>}
|
|
23
|
+
*/
|
|
24
|
+
export declare function readResourceLog({ store, controller, expectedMethod, pinStore }: {
|
|
25
|
+
store: ResourceLogStore;
|
|
26
|
+
controller: ResourceLogController;
|
|
27
|
+
expectedMethod: string;
|
|
28
|
+
pinStore: ResourceLogPinStore;
|
|
29
|
+
}): Promise<{
|
|
30
|
+
verified: VerifiedResourceLog;
|
|
31
|
+
etag?: string;
|
|
32
|
+
} | null>;
|
|
33
|
+
/**
|
|
34
|
+
* Appends one state change: verify, build against the verified head, CAS,
|
|
35
|
+
* rebase-and-retry on conflict, confirm by read-back. `buildState` is the
|
|
36
|
+
* rebase hook -- it is called with the current verified log on every attempt
|
|
37
|
+
* and returns the full next state built on THAT head's state (or `null` to
|
|
38
|
+
* signal the change is already present, making a re-run converge instead of
|
|
39
|
+
* duplicating an entry). Refuses a log whose verified head is a terminal
|
|
40
|
+
* handover entry ({@link ResourceLogClosedError}).
|
|
41
|
+
*
|
|
42
|
+
* @param options {object}
|
|
43
|
+
* @param options.store {ResourceLogStore}
|
|
44
|
+
* @param options.controller {ResourceLogController}
|
|
45
|
+
* @param options.expectedMethod {string}
|
|
46
|
+
* @param options.pinStore {ResourceLogPinStore}
|
|
47
|
+
* @param options.signer {ResourceLogSigner}
|
|
48
|
+
* @param options.buildState {function} `(verified) => state | null` -- the
|
|
49
|
+
* full next state rebased on the verified head, or `null` when the head
|
|
50
|
+
* already carries the change
|
|
51
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
52
|
+
* @param [options.maxAttempts] {number} CAS attempts before giving up
|
|
53
|
+
* (default 3)
|
|
54
|
+
* @returns {Promise<VerifiedResourceLog>} the read-back, re-verified log
|
|
55
|
+
* (whether or not this call appended)
|
|
56
|
+
*/
|
|
57
|
+
export declare function appendResourceLog({ store, controller, expectedMethod, pinStore, signer, buildState, versionTime, maxAttempts }: {
|
|
58
|
+
store: ResourceLogStore;
|
|
59
|
+
controller: ResourceLogController;
|
|
60
|
+
expectedMethod: string;
|
|
61
|
+
pinStore: ResourceLogPinStore;
|
|
62
|
+
signer: ResourceLogSigner;
|
|
63
|
+
buildState: (verified: VerifiedResourceLog) => Promise<ResourceLogEntry['state'] | null> | ResourceLogEntry['state'] | null;
|
|
64
|
+
versionTime?: string;
|
|
65
|
+
maxAttempts?: number;
|
|
66
|
+
}): Promise<VerifiedResourceLog>;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a log with its genesis entry, guarded create-if-absent, and
|
|
69
|
+
* confirms by read-back. Losing the create race to a concurrent provisioner
|
|
70
|
+
* adopts the winner's log (the create is CAS, never clobbering): the served
|
|
71
|
+
* log is verified and pinned, and the caller reconciles its intended state
|
|
72
|
+
* through an ordinary {@link appendResourceLog}. First contact is where the
|
|
73
|
+
* pin is established, so the pin store is written either way.
|
|
74
|
+
*
|
|
75
|
+
* @param options {object}
|
|
76
|
+
* @param options.store {ResourceLogStore}
|
|
77
|
+
* @param options.controller {ResourceLogController}
|
|
78
|
+
* @param options.method {string} the format identifier to declare
|
|
79
|
+
* @param options.pinStore {ResourceLogPinStore}
|
|
80
|
+
* @param options.signer {ResourceLogSigner}
|
|
81
|
+
* @param options.state {ResourceLogEntry['state']} the full initial state
|
|
82
|
+
* @param [options.previousLog] {object} handover successors only
|
|
83
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
84
|
+
* @returns {Promise<{ verified: VerifiedResourceLog; created: boolean }>}
|
|
85
|
+
* the verified log as it now stands, and whether this call created it
|
|
86
|
+
*/
|
|
87
|
+
export declare function createResourceLog({ store, controller, method, pinStore, signer, state, previousLog, versionTime }: {
|
|
88
|
+
store: ResourceLogStore;
|
|
89
|
+
controller: ResourceLogController;
|
|
90
|
+
method: string;
|
|
91
|
+
pinStore: ResourceLogPinStore;
|
|
92
|
+
signer: ResourceLogSigner;
|
|
93
|
+
state: ResourceLogEntry['state'];
|
|
94
|
+
previousLog?: {
|
|
95
|
+
scid: string;
|
|
96
|
+
head: string;
|
|
97
|
+
};
|
|
98
|
+
versionTime?: string;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
verified: VerifiedResourceLog;
|
|
101
|
+
created: boolean;
|
|
102
|
+
}>;
|
|
103
|
+
//# sourceMappingURL=append.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"append.d.ts","sourceRoot":"","sources":["../../src/resourceLog/append.ts"],"names":[],"mappings":"AAeA,OAAO,EAEL,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACtB,MAAM,yBAAyB,CAAA;AAChC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAA;AAE5D,OAAO,EAGL,KAAK,iBAAiB,EACvB,MAAM,YAAY,CAAA;AACnB,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AACnD,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,aAAa,CAAA;AAEzE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,eAAe,CAAC,EACpC,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACT,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAA;IACvB,UAAU,EAAE,qBAAqB,CAAA;IACjC,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,mBAAmB,CAAA;CAC9B,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,mBAAmB,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAcnE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,KAAK,EACL,UAAU,EACV,cAAc,EACd,QAAQ,EACR,MAAM,EACN,UAAU,EACV,WAAW,EACX,WAAe,EAChB,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAA;IACvB,UAAU,EAAE,qBAAqB,CAAA;IACjC,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,MAAM,EAAE,iBAAiB,CAAA;IACzB,UAAU,EAAE,CACV,QAAQ,EAAE,mBAAmB,KAE7B,OAAO,CAAC,gBAAgB,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,GAAG,IAAI,CAAA;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CA+D/B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,iBAAiB,CAAC,EACtC,KAAK,EACL,UAAU,EACV,MAAM,EACN,QAAQ,EACR,MAAM,EACN,KAAK,EACL,WAAW,EACX,WAAW,EACZ,EAAE;IACD,KAAK,EAAE,gBAAgB,CAAA;IACvB,UAAU,EAAE,qBAAqB,CAAA;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,MAAM,EAAE,iBAAiB,CAAA;IACzB,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAChC,WAAW,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAA;IAC5C,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,mBAAmB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC,CAmC/D"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The append path (App Connect spec `#log-append`): read the full log and
|
|
6
|
+
* verify it (an entry is never built on an unverified head), build the new
|
|
7
|
+
* entry against the verified head anchored at the writer's current verified
|
|
8
|
+
* controller head, write compare-and-swapped on the read's validator, and on
|
|
9
|
+
* conflict re-read, re-verify, rebase, retry. A write acknowledgement is a
|
|
10
|
+
* promise, not a fact: every append is confirmed by reading the log back and
|
|
11
|
+
* re-verifying the extended history before the append -- or any ceremony step
|
|
12
|
+
* gated on it -- is treated as durable. The chain-head pin advances on every
|
|
13
|
+
* successful verification along the way, and only ever forward.
|
|
14
|
+
*/
|
|
15
|
+
import { PreconditionFailedError } from '@interop/was-client';
|
|
16
|
+
import { confirmAppend } from '@interop/was-client/log';
|
|
17
|
+
import { ResourceLogClosedError } from './errors.js';
|
|
18
|
+
import { buildResourceLogEntry, buildResourceLogGenesis } from './entry.js';
|
|
19
|
+
import { verifyResourceLog } from './verify.js';
|
|
20
|
+
/**
|
|
21
|
+
* Reads and fully verifies a log through the store seam, advancing the
|
|
22
|
+
* chain-head pin. Resolves `null` when the log resource does not exist yet
|
|
23
|
+
* (the pre-genesis state). The one read entry point every consumer -- a
|
|
24
|
+
* login-time roster read, a pre-append verification, a first-contact
|
|
25
|
+
* bootstrap -- goes through, so the pin rules cannot be bypassed by reading
|
|
26
|
+
* around them.
|
|
27
|
+
*
|
|
28
|
+
* @param options {object}
|
|
29
|
+
* @param options.store {ResourceLogStore} the log's transport seam
|
|
30
|
+
* @param options.controller {ResourceLogController} the verified controller
|
|
31
|
+
* view
|
|
32
|
+
* @param options.expectedMethod {string} the format identifier expected
|
|
33
|
+
* (also confirming any `history` dispatch hint the caller followed)
|
|
34
|
+
* @param options.pinStore {ResourceLogPinStore} this client's pin for this
|
|
35
|
+
* log
|
|
36
|
+
* @returns {Promise<{ verified: VerifiedResourceLog; etag?: string } | null>}
|
|
37
|
+
*/
|
|
38
|
+
export async function readResourceLog({ store, controller, expectedMethod, pinStore }) {
|
|
39
|
+
const current = await store.read();
|
|
40
|
+
if (current === null) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const pin = await pinStore.read();
|
|
44
|
+
const verified = await verifyResourceLog({
|
|
45
|
+
entries: current.entries,
|
|
46
|
+
controller,
|
|
47
|
+
expectedMethod,
|
|
48
|
+
pin
|
|
49
|
+
});
|
|
50
|
+
await pinStore.write(verified.pin);
|
|
51
|
+
return { verified, etag: current.etag };
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Appends one state change: verify, build against the verified head, CAS,
|
|
55
|
+
* rebase-and-retry on conflict, confirm by read-back. `buildState` is the
|
|
56
|
+
* rebase hook -- it is called with the current verified log on every attempt
|
|
57
|
+
* and returns the full next state built on THAT head's state (or `null` to
|
|
58
|
+
* signal the change is already present, making a re-run converge instead of
|
|
59
|
+
* duplicating an entry). Refuses a log whose verified head is a terminal
|
|
60
|
+
* handover entry ({@link ResourceLogClosedError}).
|
|
61
|
+
*
|
|
62
|
+
* @param options {object}
|
|
63
|
+
* @param options.store {ResourceLogStore}
|
|
64
|
+
* @param options.controller {ResourceLogController}
|
|
65
|
+
* @param options.expectedMethod {string}
|
|
66
|
+
* @param options.pinStore {ResourceLogPinStore}
|
|
67
|
+
* @param options.signer {ResourceLogSigner}
|
|
68
|
+
* @param options.buildState {function} `(verified) => state | null` -- the
|
|
69
|
+
* full next state rebased on the verified head, or `null` when the head
|
|
70
|
+
* already carries the change
|
|
71
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
72
|
+
* @param [options.maxAttempts] {number} CAS attempts before giving up
|
|
73
|
+
* (default 3)
|
|
74
|
+
* @returns {Promise<VerifiedResourceLog>} the read-back, re-verified log
|
|
75
|
+
* (whether or not this call appended)
|
|
76
|
+
*/
|
|
77
|
+
export async function appendResourceLog({ store, controller, expectedMethod, pinStore, signer, buildState, versionTime, maxAttempts = 3 }) {
|
|
78
|
+
let lastConflict;
|
|
79
|
+
for (let attempt = 0; attempt < maxAttempts; attempt++) {
|
|
80
|
+
const current = await readResourceLog({
|
|
81
|
+
store,
|
|
82
|
+
controller,
|
|
83
|
+
expectedMethod,
|
|
84
|
+
pinStore
|
|
85
|
+
});
|
|
86
|
+
if (current === null) {
|
|
87
|
+
throw new Error('Cannot append to the resource log: the log does not exist yet ' +
|
|
88
|
+
'(create it with its genesis entry first).');
|
|
89
|
+
}
|
|
90
|
+
const { verified, etag } = current;
|
|
91
|
+
if (verified.terminal) {
|
|
92
|
+
throw new ResourceLogClosedError({ nextLog: verified.terminal });
|
|
93
|
+
}
|
|
94
|
+
if (etag === undefined) {
|
|
95
|
+
throw new Error('Cannot append to the resource log: the backend returned no ' +
|
|
96
|
+
'validator, and the profile forbids an unconditional write.');
|
|
97
|
+
}
|
|
98
|
+
const state = await buildState(verified);
|
|
99
|
+
if (state === null) {
|
|
100
|
+
// The head already carries the change -- a torn earlier run landed it,
|
|
101
|
+
// or a concurrent writer did. Converged.
|
|
102
|
+
return verified;
|
|
103
|
+
}
|
|
104
|
+
const entry = await buildResourceLogEntry({
|
|
105
|
+
head: verified.head,
|
|
106
|
+
state,
|
|
107
|
+
controller,
|
|
108
|
+
signer,
|
|
109
|
+
versionTime
|
|
110
|
+
});
|
|
111
|
+
try {
|
|
112
|
+
await store.append(entry, { ifMatch: etag });
|
|
113
|
+
}
|
|
114
|
+
catch (err) {
|
|
115
|
+
if (err instanceof PreconditionFailedError) {
|
|
116
|
+
// A concurrent append won the CAS: re-read, re-verify, rebase, retry.
|
|
117
|
+
lastConflict = err;
|
|
118
|
+
continue;
|
|
119
|
+
}
|
|
120
|
+
throw err;
|
|
121
|
+
}
|
|
122
|
+
const readBack = await confirmAppend({ store, entry });
|
|
123
|
+
const confirmed = await verifyResourceLog({
|
|
124
|
+
entries: readBack.entries,
|
|
125
|
+
controller,
|
|
126
|
+
expectedMethod,
|
|
127
|
+
pin: await pinStore.read()
|
|
128
|
+
});
|
|
129
|
+
await pinStore.write(confirmed.pin);
|
|
130
|
+
return confirmed;
|
|
131
|
+
}
|
|
132
|
+
throw new Error(`Appending to the resource log lost the compare-and-swap race ` +
|
|
133
|
+
`${maxAttempts} times in a row.`, { cause: lastConflict });
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Creates a log with its genesis entry, guarded create-if-absent, and
|
|
137
|
+
* confirms by read-back. Losing the create race to a concurrent provisioner
|
|
138
|
+
* adopts the winner's log (the create is CAS, never clobbering): the served
|
|
139
|
+
* log is verified and pinned, and the caller reconciles its intended state
|
|
140
|
+
* through an ordinary {@link appendResourceLog}. First contact is where the
|
|
141
|
+
* pin is established, so the pin store is written either way.
|
|
142
|
+
*
|
|
143
|
+
* @param options {object}
|
|
144
|
+
* @param options.store {ResourceLogStore}
|
|
145
|
+
* @param options.controller {ResourceLogController}
|
|
146
|
+
* @param options.method {string} the format identifier to declare
|
|
147
|
+
* @param options.pinStore {ResourceLogPinStore}
|
|
148
|
+
* @param options.signer {ResourceLogSigner}
|
|
149
|
+
* @param options.state {ResourceLogEntry['state']} the full initial state
|
|
150
|
+
* @param [options.previousLog] {object} handover successors only
|
|
151
|
+
* @param [options.versionTime] {string} RFC3339 UTC; defaults to now
|
|
152
|
+
* @returns {Promise<{ verified: VerifiedResourceLog; created: boolean }>}
|
|
153
|
+
* the verified log as it now stands, and whether this call created it
|
|
154
|
+
*/
|
|
155
|
+
export async function createResourceLog({ store, controller, method, pinStore, signer, state, previousLog, versionTime }) {
|
|
156
|
+
const genesis = await buildResourceLogGenesis({
|
|
157
|
+
state,
|
|
158
|
+
method,
|
|
159
|
+
controller,
|
|
160
|
+
signer,
|
|
161
|
+
previousLog,
|
|
162
|
+
versionTime
|
|
163
|
+
});
|
|
164
|
+
let created = true;
|
|
165
|
+
try {
|
|
166
|
+
await store.create(genesis);
|
|
167
|
+
}
|
|
168
|
+
catch (err) {
|
|
169
|
+
if (!(err instanceof PreconditionFailedError)) {
|
|
170
|
+
throw err;
|
|
171
|
+
}
|
|
172
|
+
created = false;
|
|
173
|
+
}
|
|
174
|
+
const current = created
|
|
175
|
+
? await confirmAppend({ store, entry: genesis })
|
|
176
|
+
: await store.read();
|
|
177
|
+
if (current === null) {
|
|
178
|
+
throw new Error('The resource log create lost its guarded-create race, but no log ' +
|
|
179
|
+
'was served on re-read.');
|
|
180
|
+
}
|
|
181
|
+
const verified = await verifyResourceLog({
|
|
182
|
+
entries: current.entries,
|
|
183
|
+
controller,
|
|
184
|
+
expectedMethod: method,
|
|
185
|
+
pin: await pinStore.read()
|
|
186
|
+
});
|
|
187
|
+
await pinStore.write(verified.pin);
|
|
188
|
+
return { verified, created };
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=append.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"append.js","sourceRoot":"","sources":["../../src/resourceLog/append.ts"],"names":[],"mappings":"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"}
|