@interop/zcap 10.1.0 → 11.0.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 (48) hide show
  1. package/README.md +21 -3
  2. package/dist/CapabilityDelegation.d.ts +173 -0
  3. package/dist/CapabilityDelegation.d.ts.map +1 -0
  4. package/dist/CapabilityDelegation.js +372 -0
  5. package/dist/CapabilityDelegation.js.map +1 -0
  6. package/dist/CapabilityInvocation.d.ts +151 -0
  7. package/dist/CapabilityInvocation.d.ts.map +1 -0
  8. package/dist/CapabilityInvocation.js +365 -0
  9. package/dist/CapabilityInvocation.js.map +1 -0
  10. package/dist/CapabilityProofPurpose.d.ts +203 -0
  11. package/dist/CapabilityProofPurpose.d.ts.map +1 -0
  12. package/dist/CapabilityProofPurpose.js +531 -0
  13. package/dist/CapabilityProofPurpose.js.map +1 -0
  14. package/dist/constants.d.ts +11 -0
  15. package/dist/constants.d.ts.map +1 -0
  16. package/dist/constants.js +23 -0
  17. package/dist/constants.js.map +1 -0
  18. package/dist/index.d.ts +25 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +40 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/types.d.ts +224 -0
  23. package/dist/types.d.ts.map +1 -0
  24. package/dist/types.js +2 -0
  25. package/dist/types.js.map +1 -0
  26. package/dist/utils.d.ts +250 -0
  27. package/dist/utils.d.ts.map +1 -0
  28. package/dist/utils.js +591 -0
  29. package/dist/utils.js.map +1 -0
  30. package/package.json +47 -34
  31. package/lib/CapabilityDelegation.js +0 -312
  32. package/lib/CapabilityInvocation.js +0 -343
  33. package/lib/CapabilityProofPurpose.js +0 -538
  34. package/lib/constants.js +0 -32
  35. package/lib/index.js +0 -55
  36. package/lib/utils.js +0 -673
  37. package/types/lib/CapabilityDelegation.d.ts +0 -101
  38. package/types/lib/CapabilityDelegation.d.ts.map +0 -1
  39. package/types/lib/CapabilityInvocation.d.ts +0 -100
  40. package/types/lib/CapabilityInvocation.d.ts.map +0 -1
  41. package/types/lib/CapabilityProofPurpose.d.ts +0 -126
  42. package/types/lib/CapabilityProofPurpose.d.ts.map +0 -1
  43. package/types/lib/constants.d.ts +0 -15
  44. package/types/lib/constants.d.ts.map +0 -1
  45. package/types/lib/index.d.ts +0 -42
  46. package/types/lib/index.d.ts.map +0 -1
  47. package/types/lib/utils.d.ts +0 -308
  48. package/types/lib/utils.d.ts.map +0 -1
package/lib/utils.js DELETED
@@ -1,673 +0,0 @@
1
- /*!
2
- * Copyright (c) 2018-2024 Digital Bazaar, Inc. All rights reserved.
3
- */
4
- import {
5
- MAX_CHAIN_LENGTH, ZCAP_CONTEXT_URL, ZCAP_ROOT_PREFIX
6
- } from './constants.js';
7
-
8
- /**
9
- * Creates a root capability from a root controller and a root invocation
10
- * target.
11
- *
12
- * @param {object} options - The options.
13
- * @param {string|string[]} options.controller - The root controller.
14
- * @param {string} options.invocationTarget - The root invocation target.
15
- *
16
- * @returns {IRootZcap} The root capability.
17
- */
18
- export function createRootCapability({controller, invocationTarget}) {
19
- return {
20
- '@context': ZCAP_CONTEXT_URL,
21
- id: `${ZCAP_ROOT_PREFIX}${encodeURIComponent(invocationTarget)}`,
22
- controller,
23
- invocationTarget
24
- };
25
- }
26
-
27
- /**
28
- * Retrieves the controller(s) from a capability.
29
- *
30
- * @param {object} options - The options.
31
- * @param {IZcap} options.capability - The authorization capability (zcap).
32
- *
33
- * @returns {string[]} The controller(s) for the capability.
34
- */
35
- export function getControllers({capability}) {
36
- const {controller} = capability;
37
- if(!controller) {
38
- throw new Error('Capability controller not found.');
39
- }
40
- return Array.isArray(controller) ? controller : [controller];
41
- }
42
-
43
- /**
44
- * Returns true if the given verification method is a controller (or is
45
- * controlled by a controller) of the given capability.
46
- *
47
- * @param {object} options - The options.
48
- * @param {IZcap} options.capability - The authorization capability (zcap).
49
- * @param {object} options.verificationMethod - The verification method to
50
- * check.
51
- *
52
- * @returns {boolean} `true` if the controller matches, `false` if not.
53
- */
54
- export function isController({capability, verificationMethod}) {
55
- const controllers = getControllers({capability});
56
- return controllers.includes(verificationMethod.controller) ||
57
- controllers.includes(verificationMethod.id);
58
- }
59
-
60
- /**
61
- * Retrieves the allowed actions from a capability.
62
- *
63
- * @param {object} options - The options.
64
- * @param {IZcap} options.capability - The authorization capability (zcap).
65
- *
66
- * @returns {string[]} Allowed actions.
67
- */
68
- export function getAllowedActions({capability}) {
69
- const {allowedAction} = capability;
70
- if(!allowedAction) {
71
- return [];
72
- }
73
- if(Array.isArray(allowedAction)) {
74
- return allowedAction;
75
- }
76
- return [allowedAction];
77
- }
78
-
79
- /**
80
- * Retrieves the target from a capability.
81
- *
82
- * @param {object} options - The options.
83
- * @param {IZcap} options.capability - The authorization capability (zcap).
84
- *
85
- * @returns {string} - Capability target.
86
- */
87
- export function getTarget({capability}) {
88
- // zcaps MUST have an `invocationTarget` that is a string
89
- return capability.invocationTarget;
90
- }
91
-
92
- /**
93
- * Retrieves the delegation proof(s) for a capability that is associated with
94
- * its parent capability. A capability that has no parent or no associated
95
- * delegation proofs will cause this function to return an empty array.
96
- *
97
- * @param {object} options - The options.
98
- * @param {IZcap} options.capability - The authorization capability.
99
- *
100
- * @returns {ICapabilityDelegationProof[]} Any `capabilityDelegation` proof
101
- * objects attached to the given capability.
102
- */
103
- export function getDelegationProofs({capability}) {
104
- // capability is root or capability has no `proof`, then it has no relevant
105
- // delegation proofs
106
- if(!capability.parentCapability || !capability.proof) {
107
- return [];
108
- }
109
- let {proof} = capability;
110
- if(!Array.isArray(proof)) {
111
- proof = [proof];
112
- }
113
- return proof.filter(p => p && p.proofPurpose === 'capabilityDelegation');
114
- }
115
-
116
- /**
117
- * Gets the `capabilityChain` associated with the given capability.
118
- *
119
- * @param {object} options - The options.
120
- * @param {IZcap} options.capability - The authorization capability.
121
- *
122
- * @returns {Array<string|IDelegatedZcap>} The capability chain entries
123
- * (root to parent), as stored in the delegation proof.
124
- */
125
- export function getCapabilityChain({capability}) {
126
- if(!capability.parentCapability) {
127
- // root capability has no chain
128
- return [];
129
- }
130
-
131
- const proofs = getDelegationProofs({capability});
132
- if(proofs.length !== 1) {
133
- throw new Error(
134
- 'Cannot get capability chain; capability is invalid; it is not the ' +
135
- 'root capability yet it does not have exactly one delegation proof.');
136
- }
137
-
138
- const {capabilityChain} = proofs[0];
139
- if(!(capabilityChain && Array.isArray(capabilityChain))) {
140
- throw new Error(
141
- 'Cannot get capability chain; capability is invalid; it does not have ' +
142
- 'a "capabilityChain" array in its delegation proof.');
143
- }
144
-
145
- return capabilityChain.slice();
146
- }
147
-
148
- /**
149
- * Determines if the given `invocationTarget` is valid given a
150
- * `baseInvocationTarget`.
151
- *
152
- * To check for a proper delegation, `invocationTarget` must be the child
153
- * capability's `invocationTarget` and `baseInvocationTarget` must be the
154
- * parent capability's `invocationTarget`.
155
- *
156
- * To check for a proper invocation, `invocationTarget` must be the value from
157
- * the invocation proof and `baseInvocationTarget` must be the invoked
158
- * capability's `invocationTarget`.
159
- *
160
- * @param {object} options - The options.
161
- * @param {string} options.invocationTarget - The invocation target to check.
162
- * @param {string} options.baseInvocationTarget - The base invocation target.
163
- * @param {boolean} options.allowTargetAttenuation - `true` to allow target
164
- * attenuation.
165
- *
166
- * @returns {boolean} `true` if the target is valid, `false` if not.
167
- */
168
- export function isValidTarget({
169
- invocationTarget, baseInvocationTarget, allowTargetAttenuation
170
- }) {
171
- // direct match, valid
172
- if(baseInvocationTarget === invocationTarget) {
173
- return true;
174
- }
175
- if(allowTargetAttenuation) {
176
- /* Note: When `allowTargetAttenuation=true`, a zcap can be invoked with
177
- a more narrow target and delegated zcap can have a different invocation
178
- target from its parent. Here we must ensure that the invocation target
179
- has a proper prefix relative to the base one we're comparing against.
180
-
181
- If the `baseInvocationTarget` already has a query (has `?`) then the
182
- suffix that follows it must start with `&`. Otherwise, it may start
183
- with either `/` or `?`. */
184
- const prefixes = [];
185
- if(baseInvocationTarget.includes('?')) {
186
- // query already present in base invocation target, so only accept new
187
- // variables in the query
188
- prefixes.push(`${baseInvocationTarget}&`);
189
- } else {
190
- // accept path-based attenuation or new query-based attenuation
191
- prefixes.push(`${baseInvocationTarget}/`);
192
- prefixes.push(`${baseInvocationTarget}?`);
193
- }
194
- if(prefixes.some(prefix => invocationTarget.startsWith(prefix))) {
195
- return true;
196
- }
197
- }
198
- // not a match
199
- return false;
200
- }
201
-
202
- /**
203
- * Creates a capability chain for delegating a capability from the
204
- * given `parentCapability`.
205
- *
206
- * @param {object} options - The options.
207
- * @param {string|IZcap} options.parentCapability - The parent capability from
208
- * which to compute the capability chain (a root zcap ID string, or a full
209
- * root or delegated zcap object).
210
- * @param {boolean} options._skipLocalValidationForTesting - Private.
211
- *
212
- * @returns {Array<string|IDelegatedZcap>} The computed capability chain to be
213
- * included in a capability delegation proof.
214
- */
215
- export function computeCapabilityChain({
216
- parentCapability, _skipLocalValidationForTesting
217
- }) {
218
- // if parent capability is root (string or no parent of its own)
219
- const type = typeof parentCapability;
220
- if(type === 'string') {
221
- return [parentCapability];
222
- }
223
- if(!parentCapability.parentCapability) {
224
- // capability must be a root zcap
225
- checkCapability({capability: parentCapability, expectRoot: true});
226
- return [parentCapability.id];
227
- }
228
-
229
- // capability must be a delegated zcap, check it and get its chain
230
- checkCapability({capability: parentCapability, expectRoot: false});
231
- const proofs = getDelegationProofs({capability: parentCapability});
232
- if(proofs.length !== 1) {
233
- throw new Error(
234
- 'Cannot compute capability chain; parent capability is invalid; it is ' +
235
- 'not the root capability yet it does not have exactly one delegation ' +
236
- 'proof.');
237
- }
238
-
239
- const {capabilityChain} = proofs[0];
240
- if(!(capabilityChain && Array.isArray(capabilityChain))) {
241
- throw new Error(
242
- 'Cannot compute capability chain; parent capability is invalid; it ' +
243
- 'does not have a "capabilityChain" array in its delegation proof.');
244
- }
245
-
246
- // validate parent capability chain to help prevent bad delegations
247
- if(!_skipLocalValidationForTesting) {
248
- // ensure that all `capabilityChain` entries except the last are strings
249
- const lastRequiredType = capabilityChain.length > 1 ?
250
- 'object' : 'string';
251
- const lastIndex = capabilityChain.length - 1;
252
- for(const [i, entry] of capabilityChain.entries()) {
253
- const entryType = typeof entry;
254
- if(!((i === lastIndex && entryType === lastRequiredType) ||
255
- i !== lastIndex && entryType === 'string')) {
256
- throw new TypeError(
257
- 'Cannot compute capability chain; parent capability chain is ' +
258
- 'invalid; it must consist of strings of capability IDs except ' +
259
- 'the last capability if it is delegated, in which case it must ' +
260
- 'be an object with an "id" property that is a string.');
261
- }
262
- }
263
- }
264
-
265
- // if last zcap is embedded, change it to a reference
266
- const newChain = capabilityChain.slice(0, capabilityChain.length - 1);
267
- const last = capabilityChain[capabilityChain.length - 1];
268
- if(typeof last === 'string') {
269
- newChain.push(last);
270
- } else {
271
- newChain.push(last.id);
272
- }
273
- newChain.push(parentCapability);
274
-
275
- // ensure new chain uses absolute URLs
276
- for(const entry of newChain) {
277
- if((typeof entry === 'string' && !entry.includes(':')) ||
278
- typeof entry === 'object' && !entry.id.includes(':')) {
279
- throw new Error(
280
- 'Cannot compute capability chain; parent capability chain is ' +
281
- 'invalid because uses relative URL(s) in its capability chain.');
282
- }
283
- }
284
-
285
- return newChain;
286
- }
287
-
288
- /**
289
- * Dereferences the capability chain associated with the given capability,
290
- * ensuring it passes a number of validation checks.
291
- *
292
- * A delegated zcap's chain has a reference to a root zcap. A verifier must
293
- * provide a hook (`getRootCapability`) to dereference this root zcap since
294
- * the root zcap has no delegation proof and must therefore be trusted by
295
- * the verifier. If the root zcap can't be dereferenced by the trusted hook,
296
- * then an authorization error must be thrown by that hook.
297
- *
298
- * This function will dereference the root zcap and then dereference all of
299
- * the embedded delegated zcaps from the chain, combining them into a single
300
- * array containing full zcaps ordered from root => tail.
301
- *
302
- * The dereferenced chain (result of this function) should then compare the
303
- * root zcap's ID against a list of expected root capabilities, throwing
304
- * an error if none of them match. Otherwise, the dereferenced chain should
305
- * then be processed to ensure that all delegation rules have been followed.
306
- * If checking an invocation, it should also be ensured that a combination of
307
- * an expected target and a root zcap is permitted (note it is conceivable that
308
- * a verifier may accept more than one combination, e.g., a target of `x` could
309
- * work with both root zcap `a` and `b`).
310
- *
311
- * @param {object} options - The options.
312
- * @param {string|IDelegatedZcap} options.capability - The authorization
313
- * capability to dereference the chain for. Pass a string (the root zcap ID)
314
- * to dereference a root zcap directly, or a delegated zcap object.
315
- * @param {Function} options.getRootCapability - A function for dereferencing
316
- * the root capability (the root zcap must be deref'd in a trusted way by the
317
- * verifier, it must not be untrusted input).
318
- * @param {number} [options.maxChainLength=10] - The maximum length of the
319
- * capability delegation chain (this is inclusive of `capability` itself).
320
- *
321
- * @returns {Promise<{dereferencedChain: IZcap[]}>} Resolves to an object
322
- * containing the full dereferenced chain ordered root to tail.
323
- */
324
- export async function dereferenceCapabilityChain({
325
- capability, getRootCapability, maxChainLength = MAX_CHAIN_LENGTH
326
- }) {
327
- // capability MUST be a string if it is root; root zcaps MUST always be
328
- // dereferenced via a trusted mechanism provided by the verifier as they
329
- // do not have delegation proofs
330
- if(typeof capability === 'string') {
331
- const id = capability;
332
- const {rootCapability} = await getRootCapability({id});
333
- checkCapability({capability: rootCapability, expectRoot: true});
334
- if(rootCapability.id !== id) {
335
- throw new Error(
336
- `Dereferenced root capability ID "${rootCapability.id}" does not ` +
337
- `match reference ID "${id}".`);
338
- }
339
- capability = rootCapability;
340
- } else {
341
- // ensure capability itself is valid
342
- checkCapability({capability, expectRoot: false});
343
- }
344
-
345
- // get a mapping of IDs to full zcaps as the chain is validated
346
- const dereferencedChainMap = new Map();
347
-
348
- // get the underef'd capability chain for the capability
349
- const capabilityChain = getCapabilityChain({capability});
350
-
351
- // ensure capability chain length (add 1 to be inclusive of `capability`)
352
- // does not exceed max chain length; only check this once at the start
353
- // as it produces the most sensible error -- it is true that an embedded
354
- // zcap could go over the limit but this will be caught via a congruency
355
- // check on the length instead
356
- if((capabilityChain.length + 1) > maxChainLength) {
357
- throw new Error(
358
- 'The capability chain exceeds the maximum allowed length ' +
359
- `of ${maxChainLength}.`);
360
- }
361
-
362
- // subtract one from the max chain length to start to account for
363
- // `capability` which is not present in `capabilityChain`
364
- let firstPass = true;
365
- let requiredLength = capabilityChain.length;
366
- let currentCapability = capability;
367
- let currentCapabilityChain = capabilityChain;
368
- while(currentCapabilityChain.length > 0) {
369
- if(currentCapabilityChain.length !== requiredLength) {
370
- throw new Error('The capability chain length is incongruent.');
371
- }
372
-
373
- // if `next.length > 1`, then its last entry is a delegated
374
- // capability and it MUST be fully embedded as an object; all other
375
- // entries MUST be strings
376
- const lastRequiredType = currentCapabilityChain.length > 1 ?
377
- 'object' : 'string';
378
-
379
- // validate entries and dereference delegated zcaps
380
- const lastIndex = currentCapabilityChain.length - 1;
381
- for(const [i, entry] of currentCapabilityChain.entries()) {
382
- const entryType = typeof entry;
383
- const entryIsString = entryType === 'string';
384
- const requiredType = i === lastIndex ? lastRequiredType : 'string';
385
-
386
- // ensure entry is the required type and, if it is an object, its `id`
387
- // is a string
388
- if(!(entryType === requiredType &&
389
- (entryIsString || typeof entry.id === 'string'))) {
390
- throw new TypeError(
391
- 'Capability chain is invalid; it must consist of strings ' +
392
- 'of capability IDs except the last capability if it is ' +
393
- 'delegated, in which case it must be an object with an "id" ' +
394
- 'property that is a string.');
395
- }
396
-
397
- // ensure capability ID expresses an absolute URI (i.e., it has `:`)
398
- const id = entryIsString ? entry : entry.id;
399
- if(!id.includes(':')) {
400
- throw new Error(
401
- 'Capability chain is invalid; it contains a capability ID ' +
402
- 'that is not an absolute URI.');
403
- }
404
-
405
- // ensure last entry in chain matches parent capability
406
- if(i === lastIndex && currentCapability.parentCapability &&
407
- currentCapability.parentCapability !== id) {
408
- throw new Error(
409
- 'Capability chain is invalid; the last entry does not ' +
410
- 'match the parent capability.');
411
- }
412
-
413
- if(!entryIsString) {
414
- // check zcap data model
415
- checkCapability({capability: entry, expectRoot: i === 0});
416
- }
417
-
418
- // ensure no cycles in the capability chain
419
- if(firstPass) {
420
- // on the first pass, the zcap must not have been seen yet
421
- if(id === capability.id || dereferencedChainMap.has(id)) {
422
- throw new Error('The capability chain contains a cycle.');
423
- }
424
- // add zcap to the map whether it is only a reference (an ID) or
425
- // a fully embedded zcap; this will be used to ensure no additional
426
- // zcaps are added to the chain
427
- dereferencedChainMap.set(id, entry);
428
- } else {
429
- // on non-first pass, every ID should already be in the zcap map
430
- // and they should all be strings, not objects
431
- const existing = dereferencedChainMap.get(id);
432
- if(!existing) {
433
- // the chain is inconsistent across delegated zcaps
434
- throw new Error('The capability chain is inconsistent.');
435
- }
436
- if(id === capability.id || typeof existing === 'object') {
437
- // the zcap has been deferenced before, there's a cycle
438
- throw new Error('The capability chain contains a cycle.');
439
- }
440
-
441
- // only update the zcaps map using a fully embedded zcap
442
- if(!entryIsString) {
443
- dereferencedChainMap.set(id, entry);
444
- }
445
- }
446
- }
447
-
448
- // if the chain has more than the root zcap, loop to process the
449
- // next chain from the last delegated zcap
450
- if(currentCapabilityChain.length > 1) {
451
- // next chain must be 1 shorter than the current one
452
- requiredLength--;
453
- currentCapability = currentCapabilityChain[
454
- currentCapabilityChain.length - 1];
455
- currentCapabilityChain = getCapabilityChain(
456
- {capability: currentCapability});
457
- } else {
458
- // no more chains to check
459
- break;
460
- }
461
-
462
- firstPass = false;
463
- }
464
-
465
- // dereference root zcap via provided trusted `getRootCapability` function
466
- if(capabilityChain.length > 0) {
467
- const [id] = capabilityChain;
468
- const {rootCapability} = await getRootCapability({id});
469
- checkCapability({capability: rootCapability, expectRoot: true});
470
- if(rootCapability.id !== id) {
471
- throw new Error(
472
- `Dereferenced root capability ID "${rootCapability.id}" does not ` +
473
- `match reference ID "${id}" from capability chain.`);
474
- }
475
- dereferencedChainMap.set(id, rootCapability);
476
- }
477
-
478
- // include `capability` in dereferenced map
479
- dereferencedChainMap.set(capability.id, capability);
480
- const dereferencedChain = [...dereferencedChainMap.values()];
481
-
482
- return {dereferencedChain};
483
- }
484
-
485
- export function checkProofContext({proof}) {
486
- // zcap context can appear anywhere in the array as it *is* protected
487
- const {'@context': ctx} = proof;
488
- if(!((Array.isArray(ctx) && ctx.includes(ZCAP_CONTEXT_URL)) ||
489
- ctx === ZCAP_CONTEXT_URL)) {
490
- throw new Error(
491
- `Missing required capability proof context ("${ZCAP_CONTEXT_URL}").`);
492
- }
493
- }
494
-
495
- export function hasValidAllowedAction({allowedAction, parentAllowedAction}) {
496
- // if the parent's `allowedAction` is `undefined`, then any more restrictive
497
- // action is allowed in the child
498
- if(!parentAllowedAction) {
499
- return true;
500
- }
501
-
502
- if(Array.isArray(parentAllowedAction)) {
503
- // parent's `allowedAction` must include every one from child's
504
- if(Array.isArray(allowedAction)) {
505
- return allowedAction.every(a => parentAllowedAction.includes(a));
506
- }
507
- return parentAllowedAction.includes(allowedAction);
508
- }
509
-
510
- // require exact match
511
- return (parentAllowedAction === allowedAction);
512
- }
513
-
514
- export function checkCapability({capability, expectRoot}) {
515
- const {
516
- '@context': context,
517
- id, parentCapability, invocationTarget, allowedAction, expires
518
- } = capability;
519
-
520
- const isRoot = parentCapability === undefined;
521
- if(isRoot) {
522
- if(context !== ZCAP_CONTEXT_URL) {
523
- throw new Error(
524
- 'Root capability must have an "@context" value of ' +
525
- `"${ZCAP_CONTEXT_URL}".`);
526
- }
527
- if(capability.expires !== undefined) {
528
- throw new Error('Root capability must not have an "expires" field.');
529
- }
530
- } else {
531
- if(!((Array.isArray(context) && context[0] === ZCAP_CONTEXT_URL))) {
532
- throw new Error(
533
- 'Delegated capability must have an "@context" array ' +
534
- `with "${ZCAP_CONTEXT_URL}" in its first position.`);
535
- }
536
- if(!(typeof parentCapability === 'string' &&
537
- parentCapability.includes(':'))) {
538
- throw new Error(
539
- 'Delegated capability must have a "parentCapability" with a string ' +
540
- 'value that expresses an absolute URI.');
541
- }
542
- const [proof] = getDelegationProofs({capability});
543
- if(!proof) {
544
- throw new Error('Delegated capability must have a "proof".');
545
- }
546
- if(isNaN(Date.parse(proof.created))) {
547
- throw new Error(
548
- 'Delegated capability must have a valid proof "created" date.');
549
- }
550
- if(isNaN(Date.parse(expires))) {
551
- throw new Error('Delegated capability must have a valid expires date.');
552
- }
553
- }
554
-
555
- if(!(typeof id === 'string' && id.includes(':'))) {
556
- throw new Error(
557
- 'Capability must have an "id" with a string value that expresses an ' +
558
- 'absolute URI.');
559
- }
560
- if(!(typeof invocationTarget === 'string' &&
561
- invocationTarget.includes(':'))) {
562
- throw new Error(
563
- 'Capability must have an "invocationTarget" with a string value that ' +
564
- 'expresses an absolute URI.');
565
- }
566
- if(allowedAction !== undefined && !(
567
- typeof allowedAction === 'string' ||
568
- (Array.isArray(allowedAction) && allowedAction.length > 0))) {
569
- throw new Error(
570
- 'If present on a capability, "allowedAction" must be a string or a ' +
571
- 'non-empty array.');
572
- }
573
-
574
- if(isRoot !== expectRoot) {
575
- if(expectRoot) {
576
- throw new Error(
577
- `Expected capability "${capability.id}" to be root ` +
578
- 'but it is delegated.');
579
- }
580
- throw new Error(
581
- `Expected capability "${capability.id}" to be delegated but it is root.`);
582
- }
583
- }
584
-
585
- export function compareTime({t1, t2, maxClockSkew}) {
586
- // `maxClockSkew` is in seconds, so transform to milliseconds
587
- if(Math.abs(t1 - t2) < (maxClockSkew * 1000)) {
588
- // times are equal within the max clock skew
589
- return 0;
590
- }
591
- return t1 < t2 ? -1 : 1;
592
- }
593
-
594
- /**
595
- * The zcap object shapes (`IRootZcap`, `IDelegatedZcap`,
596
- * `ICapabilityDelegationProof`, `IZcap`) live in
597
- * `@interop/data-integrity-core/zcap` (the canonical home) and are re-imported
598
- * here as typedefs for JSDoc use.
599
- *
600
- * @typedef {import('@interop/data-integrity-core/zcap').IRootZcap} IRootZcap
601
- * @typedef {import('@interop/data-integrity-core/zcap').ICapabilityDelegationProof} ICapabilityDelegationProof
602
- * @typedef {import('@interop/data-integrity-core/zcap').IDelegatedZcap} IDelegatedZcap
603
- * @typedef {import('@interop/data-integrity-core/zcap').IZcap} IZcap
604
- */
605
-
606
- /**
607
- * An inspection function result.
608
- *
609
- * @typedef {object} InspectResult
610
- * @property {boolean} [valid] - `true` if the chain passed inspection.
611
- * @property {Error} [error] - Set if inspection failed.
612
- */
613
-
614
- /**
615
- * A capability chain inspection function.
616
- *
617
- * @typedef {Function} InspectCapabilityChain
618
- * @param {CapabilityChainDetails} options - The chain details to inspect.
619
- * @returns {Promise<InspectResult>} Resolves to an inspection result.
620
- */
621
-
622
- /**
623
- * A capability. The capability is compacted into the security
624
- * context. Only the required fields are shown here, a capability will contain
625
- * additional properties.
626
- *
627
- * @typedef {object} Capability
628
- * @property {string} id - The ID of the capability.
629
- * @property {string} controller - The controller of the capability.
630
- */
631
-
632
- /**
633
- * @typedef {object} CapabilityChainDetails
634
- * @property {Capability[]} capabilityChain - The capabilities in the chain.
635
- * @property {CapabilityMeta[]} capabilityChainMeta - The results returned
636
- * from jsonld-signatures verify for each capability in the chain. Each
637
- * object contains `{verifyResult}` where each `verifyResult` is an
638
- * `InspectChainResult`.
639
- */
640
-
641
- /**
642
- * The metadata resulting from the verification of a delegated capability.
643
- *
644
- * @typedef {object} CapabilityMeta
645
- * @property {VerifyResult} verifyResult - The capability verify result, which
646
- * is `null` for the root capability.
647
- */
648
-
649
- /**
650
- * The result of running jsonld-signature's verify method.
651
- *
652
- * @typedef {object} VerifyResult
653
- * @property {boolean} verified - `true` if all the checked proofs were
654
- * successfully verified.
655
- * @property {VerifyProofResult[]} results - The verify results for each
656
- * delegation proof.
657
- */
658
-
659
- /**
660
- * The result of verifying a capability delegation proof.
661
- *
662
- * @typedef {object} VerifyProofResult
663
- * @property {VerifyProofPurposeResult} proofPurposeResult - The result from
664
- * verifying the capability delegation proof purpose.
665
- */
666
-
667
- /**
668
- * The result of verifying a capability delegation proof purpose.
669
- *
670
- * @typedef {object} VerifyProofPurposeResult
671
- * @property {string} delegator - The party that created the capability
672
- * delegation proof, i.e., the party that delegated the capability.
673
- */