@mdbase-dev/connect 0.1.0-beta.31 → 0.1.0-beta.33
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 +112 -34
- package/dist/advanced.d.ts +9 -0
- package/dist/advanced.js +6 -0
- package/dist/application-session.d.ts +39 -14
- package/dist/application-session.js +201 -70
- package/dist/async.js +11 -5
- package/dist/authority-proof.d.ts +3 -0
- package/dist/authority-proof.js +24 -0
- package/dist/browser/integrity.json +1 -1
- package/dist/browser/mdbase-connect.min.js +3 -3
- package/dist/browser/mdbase-connect.min.js.sha384 +1 -1
- package/dist/browser.d.ts +3 -0
- package/dist/browser.js +5 -0
- package/dist/capabilities.js +2 -1
- package/dist/collection-client.d.ts +36 -33
- package/dist/collection-client.js +549 -104
- package/dist/connect-authorization-helpers.d.ts +3 -0
- package/dist/connect-authorization-helpers.js +13 -0
- package/dist/connect-options.d.ts +12 -4
- package/dist/connect.d.ts +12 -4
- package/dist/connect.js +102 -103
- package/dist/connection-file-transport.d.ts +2 -2
- package/dist/connection-file-transport.js +4 -4
- package/dist/connection-notifications.d.ts +10 -4
- package/dist/connection-notifications.js +41 -23
- package/dist/connection-transport.d.ts +19 -15
- package/dist/connection-transport.js +202 -202
- package/dist/connection-types.d.ts +5 -4
- package/dist/connection.d.ts +47 -46
- package/dist/connection.js +320 -162
- package/dist/crypto-entry.d.ts +7 -0
- package/dist/crypto-entry.js +4 -0
- package/dist/crypto.js +4 -4
- package/dist/external-store.d.ts +10 -0
- package/dist/external-store.js +10 -0
- package/dist/file-transfer-internals.d.ts +23 -0
- package/dist/file-transfer-internals.js +224 -0
- package/dist/files.d.ts +36 -14
- package/dist/files.js +92 -222
- package/dist/hosted-file-request.js +3 -3
- package/dist/index.d.ts +24 -19
- package/dist/index.js +10 -18
- package/dist/internal-types.d.ts +9 -1
- package/dist/local-file-transport.d.ts +2 -2
- package/dist/local-file-transport.js +13 -13
- package/dist/mdbase-connect.d.ts +6 -4
- package/dist/mdbase-connect.js +9 -8
- package/dist/notifications.d.ts +3 -2
- package/dist/operation-helpers.d.ts +3 -3
- package/dist/operation-helpers.js +17 -34
- package/dist/operation-types.d.ts +435 -45
- package/dist/outcomes.d.ts +15 -15
- package/dist/outcomes.js +13 -1
- package/dist/pending-mutation-store.d.ts +13 -0
- package/dist/pending-mutation-store.js +64 -0
- package/dist/request-budget.d.ts +27 -0
- package/dist/request-budget.js +95 -0
- package/dist/runtime-utils.d.ts +2 -0
- package/dist/runtime-utils.js +19 -0
- package/dist/session.d.ts +5 -4
- package/dist/session.js +6 -5
- package/dist/stored-token.d.ts +10 -0
- package/dist/stored-token.js +60 -0
- package/dist/token-response.d.ts +11 -0
- package/dist/token-response.js +77 -0
- package/dist/watch-policy.d.ts +8 -0
- package/dist/watch-policy.js +12 -0
- package/package.json +12 -2
|
@@ -3,6 +3,8 @@ import { capabilityOperations, operationsForApplicationCapabilities } from "@mdb
|
|
|
3
3
|
import { effectiveCapabilities } from "./capabilities.js";
|
|
4
4
|
import { connectProblem } from "./errors.js";
|
|
5
5
|
import { connectFailure, connectSuccess } from "./outcomes.js";
|
|
6
|
+
import { createRequestBudget, requestAbortReason, resolveConnectTimeouts, withRequestBudget } from "./request-budget.js";
|
|
7
|
+
import { defaultCallbackUrl } from "./runtime-utils.js";
|
|
6
8
|
import { MdbaseSession } from "./session.js";
|
|
7
9
|
export class MdbaseMemoryVerificationStore {
|
|
8
10
|
values = new Map();
|
|
@@ -19,26 +21,67 @@ export class MdbaseMemoryVerificationStore {
|
|
|
19
21
|
/**
|
|
20
22
|
* The application-level lifecycle boundary. It derives authorization from the
|
|
21
23
|
* bundled manifest, exposes semantic capabilities, and never mutates collection
|
|
22
|
-
*
|
|
24
|
+
* setup without an explicit `applyCollectionSetup` call.
|
|
23
25
|
*/
|
|
24
26
|
export class MdbaseApplicationSession {
|
|
25
27
|
connect;
|
|
26
28
|
options;
|
|
29
|
+
timeouts;
|
|
27
30
|
listeners = new Set();
|
|
28
31
|
verificationStore;
|
|
29
32
|
snapshot = { status: "opening", connections: [] };
|
|
30
33
|
manifest = null;
|
|
34
|
+
application = null;
|
|
31
35
|
base = null;
|
|
32
36
|
stopBase;
|
|
33
|
-
|
|
37
|
+
setupAssessment = null;
|
|
34
38
|
verificationGeneration = 0;
|
|
35
|
-
|
|
39
|
+
lifecycleGeneration = 0;
|
|
40
|
+
startOperation = null;
|
|
41
|
+
constructor(connect, options, timeouts = resolveConnectTimeouts()) {
|
|
36
42
|
this.connect = connect;
|
|
37
43
|
this.options = options;
|
|
44
|
+
this.timeouts = timeouts;
|
|
38
45
|
this.verificationStore = options.verificationStore ?? defaultVerificationStore();
|
|
39
46
|
}
|
|
40
|
-
|
|
41
|
-
|
|
47
|
+
start(options) {
|
|
48
|
+
if (this.base && !this.startOperation)
|
|
49
|
+
return Promise.resolve(connectSuccess(this.snapshot));
|
|
50
|
+
const operation = this.startOperation ?? this.beginStart();
|
|
51
|
+
operation.waiters += 1;
|
|
52
|
+
return withRequestBudget(options, this.timeouts.watchStartMs, () => operation.promise)
|
|
53
|
+
.finally(() => {
|
|
54
|
+
operation.waiters -= 1;
|
|
55
|
+
if (operation.waiters === 0 && this.startOperation === operation) {
|
|
56
|
+
operation.controller.abort();
|
|
57
|
+
this.startOperation = null;
|
|
58
|
+
this.lifecycleGeneration += 1;
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
beginStart() {
|
|
63
|
+
this.snapshot = { status: "opening", connections: [] };
|
|
64
|
+
const controller = new AbortController();
|
|
65
|
+
const generation = ++this.lifecycleGeneration;
|
|
66
|
+
const operation = {
|
|
67
|
+
promise: this.startWithinBudget({ signal: controller.signal, timeoutMs: null }, generation),
|
|
68
|
+
controller,
|
|
69
|
+
waiters: 0,
|
|
70
|
+
generation
|
|
71
|
+
};
|
|
72
|
+
this.startOperation = operation;
|
|
73
|
+
const settled = () => {
|
|
74
|
+
if (this.startOperation === operation)
|
|
75
|
+
this.startOperation = null;
|
|
76
|
+
};
|
|
77
|
+
operation.promise.then(settled, settled);
|
|
78
|
+
return operation;
|
|
79
|
+
}
|
|
80
|
+
async startWithinBudget(options, generation) {
|
|
81
|
+
const registration = await this.connect.register(options);
|
|
82
|
+
if (!registration.ok)
|
|
83
|
+
return registration;
|
|
84
|
+
const manifest = await this.connect.manifest(options);
|
|
42
85
|
if (!manifest.ok)
|
|
43
86
|
return manifest;
|
|
44
87
|
const capabilities = manifest.value.requirements?.capabilities;
|
|
@@ -54,24 +97,60 @@ export class MdbaseApplicationSession {
|
|
|
54
97
|
}
|
|
55
98
|
}));
|
|
56
99
|
}
|
|
100
|
+
if (generation !== this.lifecycleGeneration || options.signal?.aborted) {
|
|
101
|
+
throw requestAbortReason(options.signal ?? new AbortController().signal);
|
|
102
|
+
}
|
|
103
|
+
this.application = registration.value;
|
|
57
104
|
this.manifest = manifest.value;
|
|
58
|
-
|
|
105
|
+
const base = new MdbaseSession(this.connect, {
|
|
59
106
|
selection: this.options.selection,
|
|
60
107
|
autoSelect: this.options.autoSelect,
|
|
61
108
|
operations: operationsForSession(capabilities)
|
|
62
109
|
});
|
|
63
|
-
this.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
110
|
+
this.base = base;
|
|
111
|
+
this.stopBase = base.subscribe(() => {
|
|
112
|
+
if (this.base === base)
|
|
113
|
+
void this.refresh();
|
|
114
|
+
});
|
|
115
|
+
try {
|
|
116
|
+
const started = await base.start(options);
|
|
117
|
+
if (!started.ok) {
|
|
118
|
+
this.cleanupBase(base);
|
|
119
|
+
return started;
|
|
120
|
+
}
|
|
121
|
+
if (generation !== this.lifecycleGeneration || options.signal?.aborted) {
|
|
122
|
+
throw requestAbortReason(options.signal ?? new AbortController().signal);
|
|
123
|
+
}
|
|
124
|
+
await this.refresh(true, options);
|
|
125
|
+
if (generation !== this.lifecycleGeneration || options.signal?.aborted) {
|
|
126
|
+
throw requestAbortReason(options.signal ?? new AbortController().signal);
|
|
127
|
+
}
|
|
128
|
+
return connectSuccess(this.snapshot);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.cleanupBase(base);
|
|
132
|
+
throw error;
|
|
133
|
+
}
|
|
69
134
|
}
|
|
70
135
|
destroy() {
|
|
136
|
+
this.lifecycleGeneration += 1;
|
|
71
137
|
this.verificationGeneration += 1;
|
|
138
|
+
this.startOperation?.controller.abort();
|
|
139
|
+
this.startOperation = null;
|
|
140
|
+
if (this.base)
|
|
141
|
+
this.cleanupBase(this.base);
|
|
142
|
+
this.application = null;
|
|
143
|
+
this.manifest = null;
|
|
144
|
+
this.setupAssessment = null;
|
|
145
|
+
this.snapshot = { status: "opening", connections: [] };
|
|
146
|
+
this.listeners.clear();
|
|
147
|
+
}
|
|
148
|
+
cleanupBase(base) {
|
|
149
|
+
if (this.base !== base)
|
|
150
|
+
return;
|
|
72
151
|
this.stopBase?.();
|
|
73
152
|
this.stopBase = undefined;
|
|
74
|
-
|
|
153
|
+
base.destroy();
|
|
75
154
|
this.base = null;
|
|
76
155
|
}
|
|
77
156
|
getSnapshot() {
|
|
@@ -97,10 +176,13 @@ export class MdbaseApplicationSession {
|
|
|
97
176
|
authorize(target, options = {}) {
|
|
98
177
|
return this.requireBase().authorize(target, options);
|
|
99
178
|
}
|
|
100
|
-
handleAuthorizationCallback(callbackUrl) {
|
|
101
|
-
return this.requireBase().handleAuthorizationCallback(callbackUrl);
|
|
179
|
+
handleAuthorizationCallback(callbackUrl, options) {
|
|
180
|
+
return this.requireBase().handleAuthorizationCallback(String(callbackUrl), options);
|
|
181
|
+
}
|
|
182
|
+
completeAuthorization(callbackUrl, options) {
|
|
183
|
+
return this.requireBase().handleAuthorizationCallback(callbackUrl === undefined ? defaultCallbackUrl() : String(callbackUrl), options);
|
|
102
184
|
}
|
|
103
|
-
ensureCapabilities(capabilities) {
|
|
185
|
+
ensureCapabilities(capabilities, options) {
|
|
104
186
|
const manifestRequirements = this.requireManifest().requirements?.capabilities;
|
|
105
187
|
const declared = new Set([
|
|
106
188
|
...(manifestRequirements?.required ?? []),
|
|
@@ -121,40 +203,50 @@ export class MdbaseApplicationSession {
|
|
|
121
203
|
}
|
|
122
204
|
})));
|
|
123
205
|
}
|
|
124
|
-
return this.requireBase().ensureOperations(operationsForIds(capabilities));
|
|
206
|
+
return this.requireBase().ensureOperations(operationsForIds(capabilities), options);
|
|
125
207
|
}
|
|
126
|
-
async
|
|
127
|
-
if (this.snapshot.status !== "
|
|
128
|
-
return connectFailure(connectProblem("collection_not_ready", "There
|
|
208
|
+
async applyCollectionSetup(options) {
|
|
209
|
+
if (this.snapshot.status !== "setup_review_required" || !this.setupAssessment) {
|
|
210
|
+
return connectFailure(connectProblem("collection_not_ready", "There is no reviewed collection setup to apply."));
|
|
129
211
|
}
|
|
130
|
-
if (this.
|
|
131
|
-
return connectFailure(connectProblem("collection_not_ready", "Resolve the
|
|
212
|
+
if (!this.setupAssessment.applicable) {
|
|
213
|
+
return connectFailure(connectProblem("collection_not_ready", "Resolve the collection setup conflicts before applying this update."));
|
|
132
214
|
}
|
|
133
215
|
const connection = this.connection();
|
|
134
216
|
if (!connection) {
|
|
135
217
|
return connectFailure(connectProblem("collection_not_ready", "The collection is not ready."));
|
|
136
218
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
219
|
+
const assessment = this.setupAssessment;
|
|
220
|
+
const input = {
|
|
221
|
+
...this.collectionSetupInput(),
|
|
222
|
+
expectedAssessmentDigest: assessment.assessmentDigest,
|
|
223
|
+
expectedCollectionRevision: assessment.collectionRevision,
|
|
224
|
+
expectedProvisionDigest: assessment.provisionDigest,
|
|
225
|
+
allowTypePackDowngrades: assessment.typePacks
|
|
226
|
+
.filter((pack) => pack.status === "downgrade")
|
|
227
|
+
.map((pack) => pack.desired.id)
|
|
228
|
+
};
|
|
229
|
+
const budget = createRequestBudget(options, this.timeouts.requestMs);
|
|
230
|
+
const requestOptions = { signal: budget.signal, timeoutMs: null };
|
|
231
|
+
try {
|
|
232
|
+
const applied = await connection.applyCollectionSetup(input, requestOptions);
|
|
144
233
|
if (!applied.ok)
|
|
145
234
|
return applied;
|
|
235
|
+
this.setupAssessment = null;
|
|
236
|
+
await this.verifySetup(this.context(connection), ++this.verificationGeneration, requestOptions);
|
|
237
|
+
return connectSuccess(this.snapshot);
|
|
238
|
+
}
|
|
239
|
+
finally {
|
|
240
|
+
budget.dispose();
|
|
146
241
|
}
|
|
147
|
-
this.reviewEntries = [];
|
|
148
|
-
await this.verifyDefinitions(this.context(connection), ++this.verificationGeneration);
|
|
149
|
-
return connectSuccess(this.snapshot);
|
|
150
242
|
}
|
|
151
|
-
async refresh(awaitVerification = false) {
|
|
243
|
+
async refresh(awaitVerification = false, options) {
|
|
152
244
|
if (!this.base || !this.manifest)
|
|
153
245
|
return;
|
|
154
246
|
const current = this.base.getSnapshot();
|
|
155
247
|
this.verificationGeneration += 1;
|
|
156
248
|
const generation = this.verificationGeneration;
|
|
157
|
-
this.
|
|
249
|
+
this.setupAssessment = null;
|
|
158
250
|
if (current.status === "unselected") {
|
|
159
251
|
this.publish({ status: "unselected", connections: current.connections });
|
|
160
252
|
return;
|
|
@@ -168,12 +260,9 @@ export class MdbaseApplicationSession {
|
|
|
168
260
|
this.publish({ status: "authorization_required", ...context });
|
|
169
261
|
return;
|
|
170
262
|
}
|
|
171
|
-
const
|
|
172
|
-
.includes("
|
|
173
|
-
|
|
174
|
-
? this.manifest.provisions?.type_packs ?? []
|
|
175
|
-
: [];
|
|
176
|
-
if (provisions.length === 0) {
|
|
263
|
+
const managesSetup = this.manifest.requirements?.capabilities?.required
|
|
264
|
+
.includes("collection.setup.apply") ?? false;
|
|
265
|
+
if (!managesSetup) {
|
|
177
266
|
this.publish({ status: "ready", verification: "verified", ...context });
|
|
178
267
|
return;
|
|
179
268
|
}
|
|
@@ -182,43 +271,34 @@ export class MdbaseApplicationSession {
|
|
|
182
271
|
this.publish({ status: "ready", verification: "cached", ...context });
|
|
183
272
|
}
|
|
184
273
|
else {
|
|
185
|
-
this.publish({ status: "
|
|
274
|
+
this.publish({ status: "checking_setup", ...context });
|
|
186
275
|
}
|
|
187
|
-
const verification = this.
|
|
276
|
+
const verification = this.verifySetup(context, generation, options);
|
|
188
277
|
if (awaitVerification)
|
|
189
278
|
await verification;
|
|
190
279
|
}
|
|
191
|
-
async
|
|
280
|
+
async verifySetup(context, generation, options) {
|
|
192
281
|
const connection = this.connection();
|
|
193
282
|
const manifest = this.requireManifest();
|
|
194
283
|
if (!connection || connection.collectionId !== context.collectionId)
|
|
195
284
|
return;
|
|
196
|
-
const
|
|
197
|
-
|
|
198
|
-
.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
if (generation !== this.verificationGeneration)
|
|
205
|
-
return;
|
|
206
|
-
if (!outcome.ok) {
|
|
207
|
-
this.publish({ status: "blocked", problem: outcome.problem, ...context });
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
if (outcome.value.status !== "current") {
|
|
211
|
-
entries.push({ provision, assessment: outcome.value });
|
|
212
|
-
}
|
|
285
|
+
const outcome = options
|
|
286
|
+
? await connection.assessCollectionSetup(this.collectionSetupInput(), options)
|
|
287
|
+
: await connection.assessCollectionSetup(this.collectionSetupInput());
|
|
288
|
+
if (generation !== this.verificationGeneration)
|
|
289
|
+
return;
|
|
290
|
+
if (!outcome.ok) {
|
|
291
|
+
this.publish({ status: "blocked", problem: outcome.problem, ...context });
|
|
292
|
+
return;
|
|
213
293
|
}
|
|
214
294
|
if (generation !== this.verificationGeneration)
|
|
215
295
|
return;
|
|
216
|
-
if (
|
|
217
|
-
this.
|
|
296
|
+
if (outcome.value.status !== "current") {
|
|
297
|
+
this.setupAssessment = outcome.value;
|
|
218
298
|
this.verificationStore.remove(verificationKey(manifest, context.collectionId));
|
|
219
299
|
this.publish({
|
|
220
|
-
status: "
|
|
221
|
-
|
|
300
|
+
status: "setup_review_required",
|
|
301
|
+
update: collectionSetupUpdate(outcome.value, manifest.provisions?.type_packs ?? []),
|
|
222
302
|
...context
|
|
223
303
|
});
|
|
224
304
|
return;
|
|
@@ -226,6 +306,21 @@ export class MdbaseApplicationSession {
|
|
|
226
306
|
this.verificationStore.write(verificationKey(manifest, context.collectionId), verificationValue(manifest));
|
|
227
307
|
this.publish({ status: "ready", verification: "verified", ...context });
|
|
228
308
|
}
|
|
309
|
+
collectionSetupInput() {
|
|
310
|
+
const manifest = this.requireManifest();
|
|
311
|
+
const application = this.requireApplication();
|
|
312
|
+
return {
|
|
313
|
+
applicationId: declarationIdFromFamilyIdentity(application.family_identity),
|
|
314
|
+
declarationDigest: `sha256:${application.manifest_digest}`,
|
|
315
|
+
requirements: {
|
|
316
|
+
configuration: manifest.requirements?.configuration ?? []
|
|
317
|
+
},
|
|
318
|
+
provisions: {
|
|
319
|
+
configuration: manifest.provisions?.configuration ?? [],
|
|
320
|
+
typePacks: manifest.provisions?.type_packs ?? []
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
}
|
|
229
324
|
context(connection) {
|
|
230
325
|
const info = connection.info();
|
|
231
326
|
return {
|
|
@@ -252,6 +347,11 @@ export class MdbaseApplicationSession {
|
|
|
252
347
|
throw new Error("Start the application session before using it.");
|
|
253
348
|
return this.manifest;
|
|
254
349
|
}
|
|
350
|
+
requireApplication() {
|
|
351
|
+
if (!this.application)
|
|
352
|
+
throw new Error("Start the application session before using it.");
|
|
353
|
+
return this.application;
|
|
354
|
+
}
|
|
255
355
|
}
|
|
256
356
|
function operationsForSession(requirements) {
|
|
257
357
|
return operationsForApplicationCapabilities(requirements);
|
|
@@ -260,8 +360,7 @@ function operationsForIds(capabilities) {
|
|
|
260
360
|
const definitions = capabilities.flatMap((id) => capabilityOperations(id));
|
|
261
361
|
return [...new Set(definitions)];
|
|
262
362
|
}
|
|
263
|
-
function definitionUpdate(
|
|
264
|
-
const { assessment } = entry;
|
|
363
|
+
function definitionUpdate(provision, assessment) {
|
|
265
364
|
const statusReason = assessment.status === "conflict"
|
|
266
365
|
? "Existing user-owned resources conflict with this application definition pack."
|
|
267
366
|
: assessment.status === "install"
|
|
@@ -269,27 +368,59 @@ function definitionUpdate(entry) {
|
|
|
269
368
|
: `This collection has a ${assessment.status} definition change to review.`;
|
|
270
369
|
return {
|
|
271
370
|
id: assessment.desired.id,
|
|
272
|
-
name:
|
|
371
|
+
name: provision.manifest.name ?? assessment.desired.id,
|
|
273
372
|
status: assessment.status,
|
|
274
373
|
applicable: assessment.applicable,
|
|
275
|
-
assessmentDigest: assessment.
|
|
374
|
+
assessmentDigest: assessment.assessmentDigest,
|
|
276
375
|
...(assessment.current ? { currentVersion: assessment.current.version } : {}),
|
|
277
376
|
desiredVersion: assessment.desired.version,
|
|
278
377
|
resources: assessment.resources,
|
|
279
|
-
contractSetups: assessment.
|
|
378
|
+
contractSetups: assessment.contractSetups,
|
|
280
379
|
canApply: assessment.applicable,
|
|
281
380
|
reason: statusReason
|
|
282
381
|
};
|
|
283
382
|
}
|
|
383
|
+
function collectionSetupUpdate(assessment, provisions) {
|
|
384
|
+
const typePacks = assessment.typePacks.map((pack) => {
|
|
385
|
+
const provision = provisions.find((candidate) => candidate.manifest.id === pack.desired.id);
|
|
386
|
+
if (!provision) {
|
|
387
|
+
throw new Error(`Collection setup returned undeclared type pack '${pack.desired.id}'.`);
|
|
388
|
+
}
|
|
389
|
+
return definitionUpdate(provision, pack);
|
|
390
|
+
});
|
|
391
|
+
const configurationChanges = assessment.configuration.filter((entry) => entry.action !== "current").length;
|
|
392
|
+
const reason = assessment.status === "conflict"
|
|
393
|
+
? "Existing collection policy conflicts with this application's required setup."
|
|
394
|
+
: `This application requires ${configurationChanges} configuration change${configurationChanges === 1 ? "" : "s"} and ${typePacks.length} definition update${typePacks.length === 1 ? "" : "s"}.`;
|
|
395
|
+
return {
|
|
396
|
+
status: assessment.status,
|
|
397
|
+
applicable: assessment.applicable,
|
|
398
|
+
assessmentDigest: assessment.assessmentDigest,
|
|
399
|
+
collectionRevision: assessment.collectionRevision,
|
|
400
|
+
provisionDigest: assessment.provisionDigest,
|
|
401
|
+
configuration: assessment.configuration,
|
|
402
|
+
typePacks,
|
|
403
|
+
canApply: assessment.applicable,
|
|
404
|
+
reason
|
|
405
|
+
};
|
|
406
|
+
}
|
|
284
407
|
function verificationKey(manifest, collectionId) {
|
|
285
408
|
return `mdbase-application-session:v1:${manifest.id}:${collectionId}`;
|
|
286
409
|
}
|
|
287
410
|
function verificationValue(manifest) {
|
|
288
411
|
return JSON.stringify({
|
|
289
412
|
capabilities: manifest.requirements?.capabilities,
|
|
290
|
-
|
|
413
|
+
requirements: manifest.requirements?.configuration ?? [],
|
|
414
|
+
provisions: manifest.provisions ?? {}
|
|
291
415
|
});
|
|
292
416
|
}
|
|
417
|
+
function declarationIdFromFamilyIdentity(familyIdentity) {
|
|
418
|
+
const prefix = "bundle:";
|
|
419
|
+
if (!familyIdentity.startsWith(prefix) || familyIdentity.length === prefix.length) {
|
|
420
|
+
throw new Error("The registered application has no valid declaration identity.");
|
|
421
|
+
}
|
|
422
|
+
return familyIdentity.slice(prefix.length);
|
|
423
|
+
}
|
|
293
424
|
function defaultVerificationStore() {
|
|
294
425
|
if (typeof localStorage !== "undefined") {
|
|
295
426
|
return {
|
package/dist/async.js
CHANGED
|
@@ -1,13 +1,19 @@
|
|
|
1
1
|
export function abortableDelay(milliseconds, signal) {
|
|
2
2
|
return new Promise((resolve, reject) => {
|
|
3
3
|
if (signal?.aborted) {
|
|
4
|
-
reject(signal
|
|
4
|
+
reject(signal?.reason ?? new DOMException("Aborted", "AbortError"));
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const cleanup = () => signal?.removeEventListener("abort", abort);
|
|
8
|
+
const timeout = setTimeout(() => {
|
|
9
|
+
cleanup();
|
|
10
|
+
resolve();
|
|
11
|
+
}, milliseconds);
|
|
12
|
+
const abort = () => {
|
|
9
13
|
clearTimeout(timeout);
|
|
10
|
-
|
|
11
|
-
|
|
14
|
+
cleanup();
|
|
15
|
+
reject(signal?.reason ?? new DOMException("Aborted", "AbortError"));
|
|
16
|
+
};
|
|
17
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
12
18
|
});
|
|
13
19
|
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { type GrantKeyStore } from "./crypto.js";
|
|
2
|
+
import type { StoredToken } from "./internal-types.js";
|
|
3
|
+
export declare function authorityProofHeaders(keyStore: GrantKeyStore, token: StoredToken, method: string, url: string, body: string | undefined, credential: string): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { RelayCryptoError, signAuthorityRequest } from "./crypto.js";
|
|
2
|
+
import { connectError, serverConnectError } from "./errors.js";
|
|
3
|
+
export async function authorityProofHeaders(keyStore, token, method, url, body, credential) {
|
|
4
|
+
if (!token.authority?.proofPublicKey)
|
|
5
|
+
return {};
|
|
6
|
+
if (!token.keyHandle) {
|
|
7
|
+
throw connectError("missing_grant_key", "Reconnect this application to restore remote authority request signing.");
|
|
8
|
+
}
|
|
9
|
+
try {
|
|
10
|
+
const target = new URL(url);
|
|
11
|
+
return await signAuthorityRequest(keyStore, token.keyHandle, token.authority.proofPublicKey, {
|
|
12
|
+
method,
|
|
13
|
+
target: `${target.pathname}${target.search}`,
|
|
14
|
+
body,
|
|
15
|
+
credential
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
catch (error) {
|
|
19
|
+
if (error instanceof RelayCryptoError) {
|
|
20
|
+
throw serverConnectError(error.code, error.message);
|
|
21
|
+
}
|
|
22
|
+
throw error;
|
|
23
|
+
}
|
|
24
|
+
}
|