@interop/was-client 0.21.0 → 0.23.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 +12 -11
- package/dist/Collection.d.ts +28 -25
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +55 -51
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts +7 -7
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +19 -18
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts +3 -2
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +5 -4
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts +19 -17
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +23 -21
- package/dist/WasClient.js.map +1 -1
- package/dist/codec.d.ts +16 -15
- package/dist/codec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.d.ts +2 -2
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +29 -28
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +9 -8
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +9 -8
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/constants.js +1 -1
- package/dist/edv/descriptorStore.d.ts +119 -0
- package/dist/edv/descriptorStore.d.ts.map +1 -0
- package/dist/edv/{markerStore.js → descriptorStore.js} +41 -40
- package/dist/edv/descriptorStore.js.map +1 -0
- package/dist/edv/docCipher.d.ts +31 -29
- package/dist/edv/docCipher.d.ts.map +1 -1
- package/dist/edv/docCipher.js +26 -24
- package/dist/edv/docCipher.js.map +1 -1
- package/dist/edv/epochCrypto.d.ts +8 -8
- package/dist/edv/epochCrypto.d.ts.map +1 -1
- package/dist/edv/epochCrypto.js +15 -14
- package/dist/edv/epochCrypto.js.map +1 -1
- package/dist/edv/epochKeys.d.ts +18 -15
- package/dist/edv/epochKeys.d.ts.map +1 -1
- package/dist/edv/epochKeys.js +20 -19
- package/dist/edv/epochKeys.js.map +1 -1
- package/dist/edv/epochMac.d.ts +11 -10
- package/dist/edv/epochMac.d.ts.map +1 -1
- package/dist/edv/epochMac.js +24 -23
- package/dist/edv/epochMac.js.map +1 -1
- package/dist/edv/index.d.ts +10 -8
- package/dist/edv/index.d.ts.map +1 -1
- package/dist/edv/index.js +9 -7
- package/dist/edv/index.js.map +1 -1
- package/dist/edv/recipients.d.ts +41 -31
- package/dist/edv/recipients.d.ts.map +1 -1
- package/dist/edv/recipients.js +90 -82
- package/dist/edv/recipients.js.map +1 -1
- package/dist/errors.d.ts +2 -2
- package/dist/errors.js +2 -2
- package/dist/internal/codec.d.ts +8 -8
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +12 -12
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/describe.d.ts +3 -3
- package/dist/sync/envelope.d.ts +2 -2
- package/dist/sync/envelope.js +2 -2
- package/dist/sync/provisioning.d.ts +10 -10
- package/dist/sync/provisioning.js +9 -9
- package/dist/sync/types.d.ts +4 -4
- package/dist/types.d.ts +5 -5
- package/package.json +3 -3
- package/dist/edv/markerStore.d.ts +0 -118
- package/dist/edv/markerStore.d.ts.map +0 -1
- package/dist/edv/markerStore.js.map +0 -1
package/dist/edv/recipients.d.ts
CHANGED
|
@@ -5,18 +5,18 @@
|
|
|
5
5
|
* Recipient and key-epoch management for multi-recipient encrypted Collections:
|
|
6
6
|
* initializing the first epoch, adding a reader (escrow -- history included),
|
|
7
7
|
* and removing a reader (the full revoke-and-rotate procedure). Each operation
|
|
8
|
-
* mutates a `CollectionEncryption`
|
|
9
|
-
* `
|
|
10
|
-
* `collection` sugar, or any explicit `store`, such as a
|
|
11
|
-
* plain JSON Resource -- and writes it back with a
|
|
12
|
-
* (`If-Match`), retrying on a concurrent change so two racing
|
|
13
|
-
* cannot clobber one another.
|
|
8
|
+
* mutates a `CollectionEncryption` descriptor through the descriptor-store seam
|
|
9
|
+
* (see `descriptorStore.ts`) -- the Collection Description's `encryption`
|
|
10
|
+
* member for the `collection` sugar, or any explicit `store`, such as a
|
|
11
|
+
* descriptor hosted as a plain JSON Resource -- and writes it back with a
|
|
12
|
+
* compare-and-swap (`If-Match`), retrying on a concurrent change so two racing
|
|
13
|
+
* recipient edits cannot clobber one another.
|
|
14
14
|
*
|
|
15
15
|
* The two axes stay separate and are both required to actually remove a reader:
|
|
16
16
|
*
|
|
17
17
|
* - **pull** -- the reader's server-side access. For a Collection this is the
|
|
18
18
|
* zcap the server checks at request time: revoking it stops the server
|
|
19
|
-
* serving that reader ciphertext. Immediate and total. A
|
|
19
|
+
* serving that reader ciphertext. Immediate and total. A descriptor whose pull
|
|
20
20
|
* axis lives elsewhere (e.g. a DID document naming the readers) supplies a
|
|
21
21
|
* `pull` action instead of the default zcap revocation.
|
|
22
22
|
* - **read** -- possession of an epoch key. Rotating the epoch means resources
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
import type { IKeyAgreementKey } from '@interop/data-integrity-core';
|
|
34
34
|
import type { Collection } from '../Collection.js';
|
|
35
35
|
import type { Space } from '../Space.js';
|
|
36
|
-
import type {
|
|
36
|
+
import type { EncryptionDescriptorStore } from './descriptorStore.js';
|
|
37
37
|
import type { CollectionEncryption, IDelegatedZcap } from '../types.js';
|
|
38
38
|
import type { RecipientPublicKey } from './epochCrypto.js';
|
|
39
39
|
export type { RecipientPublicKey } from './epochCrypto.js';
|
|
@@ -45,31 +45,41 @@ export interface OwnerKey {
|
|
|
45
45
|
keyAgreementKey: IKeyAgreementKey;
|
|
46
46
|
}
|
|
47
47
|
/**
|
|
48
|
-
* Initializes the first key epoch on a
|
|
49
|
-
* fresh epoch key, wraps it to each initial recipient, and writes
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
48
|
+
* Initializes the first key epoch on a descriptor that has no epochs yet: mints
|
|
49
|
+
* a fresh epoch key, wraps it to each initial recipient, and writes `epochs:
|
|
50
|
+
* [epoch]` / `currentEpoch` back with a compare-and-swap. After this, resources
|
|
51
|
+
* written by any recipient are encrypted under the epoch, and readers unwrap it
|
|
52
|
+
* with their own key-agreement key.
|
|
53
53
|
*
|
|
54
54
|
* On the `collection` host the collection must already be declared encrypted
|
|
55
|
-
* (its
|
|
56
|
-
* host starts absent (e.g. `
|
|
57
|
-
* not exist before the first init), the
|
|
58
|
-
* with a create-if-absent guard (`If-None-Match: *`), so
|
|
59
|
-
* inits cannot clobber one another.
|
|
55
|
+
* (its descriptor exists; this fills in the first epochs). On a store whose
|
|
56
|
+
* descriptor host starts absent (e.g. `resourceDescriptorStore`, whose roster
|
|
57
|
+
* resource does not exist before the first init), the descriptor itself is
|
|
58
|
+
* created from scratch with a create-if-absent guard (`If-None-Match: *`), so
|
|
59
|
+
* two racing first inits cannot clobber one another.
|
|
60
60
|
*
|
|
61
61
|
* @param options {object}
|
|
62
62
|
* @param [options.collection] {Collection} the (already encrypted) collection
|
|
63
|
-
* whose Description hosts the
|
|
64
|
-
*
|
|
63
|
+
* whose Description hosts the descriptor; exactly one of `collection` /
|
|
64
|
+
* `store`
|
|
65
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
65
66
|
* @param options.recipients {RecipientPublicKey[]} the initial readers' public
|
|
66
67
|
* key-agreement keys (each `id` is the reader's `kid`)
|
|
67
|
-
* @
|
|
68
|
+
* @param [options.epoch] {{ epochId: string, secret: Uint8Array }} a
|
|
69
|
+
* pre-minted first epoch to install instead of minting one -- for a caller
|
|
70
|
+
* whose epoch key already exists (e.g. a per-user key being enrolled into
|
|
71
|
+
* its wrap-set roster). The `epochId` must be the key's did:key and `secret`
|
|
72
|
+
* its raw 32-byte private key, exactly what {@link mintEpoch} returns.
|
|
73
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
68
74
|
*/
|
|
69
|
-
export declare function initRecipients({ collection, store, recipients }: {
|
|
75
|
+
export declare function initRecipients({ collection, store, recipients, epoch: premintedEpoch }: {
|
|
70
76
|
collection?: Collection;
|
|
71
|
-
store?:
|
|
77
|
+
store?: EncryptionDescriptorStore;
|
|
72
78
|
recipients: RecipientPublicKey[];
|
|
79
|
+
epoch?: {
|
|
80
|
+
epochId: string;
|
|
81
|
+
secret: Uint8Array;
|
|
82
|
+
};
|
|
73
83
|
}): Promise<CollectionEncryption>;
|
|
74
84
|
/**
|
|
75
85
|
* Adds a reader to a multi-recipient encrypted Collection. Escrow semantics: the
|
|
@@ -83,16 +93,16 @@ export declare function initRecipients({ collection, store, recipients }: {
|
|
|
83
93
|
*
|
|
84
94
|
* @param options {object}
|
|
85
95
|
* @param [options.collection] {Collection} the collection whose Description
|
|
86
|
-
* hosts the
|
|
87
|
-
* @param [options.store] {
|
|
96
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
97
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
88
98
|
* @param options.recipient {RecipientPublicKey} the new reader's public KAK
|
|
89
99
|
* @param options.owner {OwnerKey} the caller's own key-agreement key, to
|
|
90
100
|
* unwrap each epoch key for re-wrapping to the new reader
|
|
91
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
101
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
92
102
|
*/
|
|
93
103
|
export declare function addRecipient({ collection, store, recipient, owner }: {
|
|
94
104
|
collection?: Collection;
|
|
95
|
-
store?:
|
|
105
|
+
store?: EncryptionDescriptorStore;
|
|
96
106
|
recipient: RecipientPublicKey;
|
|
97
107
|
owner: OwnerKey;
|
|
98
108
|
}): Promise<CollectionEncryption>;
|
|
@@ -128,8 +138,8 @@ export declare function addRecipient({ collection, store, recipient, owner }: {
|
|
|
128
138
|
*
|
|
129
139
|
* @param options {object}
|
|
130
140
|
* @param [options.collection] {Collection} the collection whose Description
|
|
131
|
-
* hosts the
|
|
132
|
-
* @param [options.store] {
|
|
141
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
142
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
133
143
|
* @param [options.space] {Space} the collection's Space, for the default
|
|
134
144
|
* pull axis (zcap revocation); required together with `revoke` unless a
|
|
135
145
|
* custom `pull` is supplied
|
|
@@ -149,11 +159,11 @@ export declare function addRecipient({ collection, store, recipient, owner }: {
|
|
|
149
159
|
* self-describing `did:key`. May resolve `null` to signal drop-this-kid:
|
|
150
160
|
* the rotation then excludes that entry from the fresh epoch instead of
|
|
151
161
|
* throwing (subject to the no-recipients-remaining guard).
|
|
152
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
162
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
153
163
|
*/
|
|
154
164
|
export declare function removeRecipient({ collection, store, space, recipientId, revoke, pull, resolveRecipientKey }: {
|
|
155
165
|
collection?: Collection;
|
|
156
|
-
store?:
|
|
166
|
+
store?: EncryptionDescriptorStore;
|
|
157
167
|
space?: Space;
|
|
158
168
|
recipientId: string;
|
|
159
169
|
revoke?: IDelegatedZcap | IDelegatedZcap[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipients.d.ts","sourceRoot":"","sources":["../../src/edv/recipients.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"recipients.d.ts","sourceRoot":"","sources":["../../src/edv/recipients.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AACpE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAGxC,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAA;AACrE,OAAO,KAAK,EACV,oBAAoB,EAEpB,cAAc,EACf,MAAM,aAAa,CAAA;AAQpB,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAE1D,YAAY,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AAE1D;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACvB,eAAe,EAAE,gBAAgB,CAAA;CAClC;AAQD;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,cAAc,CAAC,EACnC,UAAU,EACV,KAAK,EACL,UAAU,EACV,KAAK,EAAE,cAAc,EACtB,EAAE;IACD,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,UAAU,EAAE,kBAAkB,EAAE,CAAA;IAChC,KAAK,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAA;KAAE,CAAA;CAChD,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA8ChC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAsB,YAAY,CAAC,EACjC,UAAU,EACV,KAAK,EACL,SAAS,EACT,KAAK,EACN,EAAE;IACD,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,SAAS,EAAE,kBAAkB,CAAA;IAC7B,KAAK,EAAE,QAAQ,CAAA;CAChB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAuDhC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AACH,wBAAsB,eAAe,CAAC,EACpC,UAAU,EACV,KAAK,EACL,KAAK,EACL,WAAW,EACX,MAAM,EACN,IAAI,EACJ,mBAAgD,EACjD,EAAE;IACD,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,KAAK,CAAC,EAAE,yBAAyB,CAAA;IACjC,KAAK,CAAC,EAAE,KAAK,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,CAAC,EAAE,cAAc,GAAG,cAAc,EAAE,CAAA;IAC1C,IAAI,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1B,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAA;CAC1E,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAgGhC"}
|
package/dist/edv/recipients.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PreconditionFailedError, ValidationError } from '../errors.js';
|
|
2
|
-
import {
|
|
2
|
+
import { collectionDescriptorStore } from './descriptorStore.js';
|
|
3
3
|
import { didKeyResolver, mintEpoch, unwrapEpochSecret, wrapEpochSecret } from './epochCrypto.js';
|
|
4
4
|
import { computeEpochsMac } from './epochMac.js';
|
|
5
5
|
/**
|
|
@@ -8,59 +8,66 @@ import { computeEpochsMac } from './epochMac.js';
|
|
|
8
8
|
*/
|
|
9
9
|
const MAX_CAS_ATTEMPTS = 3;
|
|
10
10
|
/**
|
|
11
|
-
* Initializes the first key epoch on a
|
|
12
|
-
* fresh epoch key, wraps it to each initial recipient, and writes
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
11
|
+
* Initializes the first key epoch on a descriptor that has no epochs yet: mints
|
|
12
|
+
* a fresh epoch key, wraps it to each initial recipient, and writes `epochs:
|
|
13
|
+
* [epoch]` / `currentEpoch` back with a compare-and-swap. After this, resources
|
|
14
|
+
* written by any recipient are encrypted under the epoch, and readers unwrap it
|
|
15
|
+
* with their own key-agreement key.
|
|
16
16
|
*
|
|
17
17
|
* On the `collection` host the collection must already be declared encrypted
|
|
18
|
-
* (its
|
|
19
|
-
* host starts absent (e.g. `
|
|
20
|
-
* not exist before the first init), the
|
|
21
|
-
* with a create-if-absent guard (`If-None-Match: *`), so
|
|
22
|
-
* inits cannot clobber one another.
|
|
18
|
+
* (its descriptor exists; this fills in the first epochs). On a store whose
|
|
19
|
+
* descriptor host starts absent (e.g. `resourceDescriptorStore`, whose roster
|
|
20
|
+
* resource does not exist before the first init), the descriptor itself is
|
|
21
|
+
* created from scratch with a create-if-absent guard (`If-None-Match: *`), so
|
|
22
|
+
* two racing first inits cannot clobber one another.
|
|
23
23
|
*
|
|
24
24
|
* @param options {object}
|
|
25
25
|
* @param [options.collection] {Collection} the (already encrypted) collection
|
|
26
|
-
* whose Description hosts the
|
|
27
|
-
*
|
|
26
|
+
* whose Description hosts the descriptor; exactly one of `collection` /
|
|
27
|
+
* `store`
|
|
28
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
28
29
|
* @param options.recipients {RecipientPublicKey[]} the initial readers' public
|
|
29
30
|
* key-agreement keys (each `id` is the reader's `kid`)
|
|
30
|
-
* @
|
|
31
|
+
* @param [options.epoch] {{ epochId: string, secret: Uint8Array }} a
|
|
32
|
+
* pre-minted first epoch to install instead of minting one -- for a caller
|
|
33
|
+
* whose epoch key already exists (e.g. a per-user key being enrolled into
|
|
34
|
+
* its wrap-set roster). The `epochId` must be the key's did:key and `secret`
|
|
35
|
+
* its raw 32-byte private key, exactly what {@link mintEpoch} returns.
|
|
36
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
31
37
|
*/
|
|
32
|
-
export async function initRecipients({ collection, store, recipients }) {
|
|
38
|
+
export async function initRecipients({ collection, store, recipients, epoch: premintedEpoch }) {
|
|
33
39
|
if (recipients.length === 0) {
|
|
34
40
|
throw new ValidationError('initRecipients needs at least one recipient to wrap the epoch key to.');
|
|
35
41
|
}
|
|
36
|
-
const { epochId, secret } = await mintEpoch();
|
|
42
|
+
const { epochId, secret } = premintedEpoch ?? (await mintEpoch());
|
|
37
43
|
const epoch = {
|
|
38
44
|
id: epochId,
|
|
39
45
|
recipients: await Promise.all(recipients.map(recipient => wrapEpochSecret({ epochSecret: secret, recipient })))
|
|
40
46
|
};
|
|
41
|
-
return
|
|
42
|
-
store:
|
|
43
|
-
// A store whose
|
|
44
|
-
// (the create-if-absent branch); a Collection Description's
|
|
45
|
-
// exists, so its adapter never reaches the seed.
|
|
47
|
+
return casUpdateDescriptor({
|
|
48
|
+
store: descriptorStoreFor({ collection, store }),
|
|
49
|
+
// A store whose descriptor starts absent initializes from a bare `edv`
|
|
50
|
+
// descriptor (the create-if-absent branch); a Collection Description's
|
|
51
|
+
// descriptor always exists, so its adapter never reaches the seed.
|
|
46
52
|
seed: { scheme: 'edv' },
|
|
47
|
-
mutate: async (
|
|
48
|
-
if (
|
|
53
|
+
mutate: async (descriptor) => {
|
|
54
|
+
if (descriptor.epochs && descriptor.epochs.length > 0) {
|
|
49
55
|
throw new ValidationError('This collection already has key epochs; use addRecipient to add a ' +
|
|
50
56
|
'reader instead of initRecipients.');
|
|
51
57
|
}
|
|
52
|
-
// Declaring the first epochs, so stamp scheme version 1 when the
|
|
53
|
-
// does not already carry one, and authenticate the epoch
|
|
54
|
-
// with a MAC keyed from this first epoch's secret (computed
|
|
55
|
-
//
|
|
58
|
+
// Declaring the first epochs, so stamp scheme version 1 when the
|
|
59
|
+
// descriptor does not already carry one, and authenticate the epoch
|
|
60
|
+
// configuration with a MAC keyed from this first epoch's secret (computed
|
|
61
|
+
// over the exact descriptor being written, since a CAS retry re-reads the
|
|
62
|
+
// descriptor).
|
|
56
63
|
const next = {
|
|
57
|
-
...
|
|
58
|
-
version:
|
|
64
|
+
...descriptor,
|
|
65
|
+
version: descriptor.version ?? 1,
|
|
59
66
|
epochs: [epoch],
|
|
60
67
|
currentEpoch: epochId
|
|
61
68
|
};
|
|
62
69
|
const epochsMac = await computeEpochsMac({
|
|
63
|
-
|
|
70
|
+
descriptor: next,
|
|
64
71
|
epochSecret: secret
|
|
65
72
|
});
|
|
66
73
|
return { ...next, epochsMac };
|
|
@@ -79,18 +86,18 @@ export async function initRecipients({ collection, store, recipients }) {
|
|
|
79
86
|
*
|
|
80
87
|
* @param options {object}
|
|
81
88
|
* @param [options.collection] {Collection} the collection whose Description
|
|
82
|
-
* hosts the
|
|
83
|
-
* @param [options.store] {
|
|
89
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
90
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
84
91
|
* @param options.recipient {RecipientPublicKey} the new reader's public KAK
|
|
85
92
|
* @param options.owner {OwnerKey} the caller's own key-agreement key, to
|
|
86
93
|
* unwrap each epoch key for re-wrapping to the new reader
|
|
87
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
94
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
88
95
|
*/
|
|
89
96
|
export async function addRecipient({ collection, store, recipient, owner }) {
|
|
90
|
-
return
|
|
91
|
-
store:
|
|
92
|
-
mutate: async (
|
|
93
|
-
const epochs =
|
|
97
|
+
return casUpdateDescriptor({
|
|
98
|
+
store: descriptorStoreFor({ collection, store }),
|
|
99
|
+
mutate: async (descriptor) => {
|
|
100
|
+
const epochs = descriptor.epochs;
|
|
94
101
|
if (!epochs || epochs.length === 0) {
|
|
95
102
|
throw new ValidationError('Cannot addRecipient: this collection has no key epochs. Call ' +
|
|
96
103
|
'initRecipients first.');
|
|
@@ -126,7 +133,7 @@ export async function addRecipient({ collection, store, recipient, owner }) {
|
|
|
126
133
|
recipients: [...epoch.recipients, wrapped]
|
|
127
134
|
};
|
|
128
135
|
}));
|
|
129
|
-
return { ...
|
|
136
|
+
return { ...descriptor, epochs: nextEpochs };
|
|
130
137
|
}
|
|
131
138
|
});
|
|
132
139
|
}
|
|
@@ -162,8 +169,8 @@ export async function addRecipient({ collection, store, recipient, owner }) {
|
|
|
162
169
|
*
|
|
163
170
|
* @param options {object}
|
|
164
171
|
* @param [options.collection] {Collection} the collection whose Description
|
|
165
|
-
* hosts the
|
|
166
|
-
* @param [options.store] {
|
|
172
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
173
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
167
174
|
* @param [options.space] {Space} the collection's Space, for the default
|
|
168
175
|
* pull axis (zcap revocation); required together with `revoke` unless a
|
|
169
176
|
* custom `pull` is supplied
|
|
@@ -183,12 +190,12 @@ export async function addRecipient({ collection, store, recipient, owner }) {
|
|
|
183
190
|
* self-describing `did:key`. May resolve `null` to signal drop-this-kid:
|
|
184
191
|
* the rotation then excludes that entry from the fresh epoch instead of
|
|
185
192
|
* throwing (subject to the no-recipients-remaining guard).
|
|
186
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
193
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
187
194
|
*/
|
|
188
195
|
export async function removeRecipient({ collection, store, space, recipientId, revoke, pull, resolveRecipientKey = defaultResolveRecipientKey }) {
|
|
189
|
-
const
|
|
196
|
+
const descriptorStore = descriptorStoreFor({ collection, store });
|
|
190
197
|
// Resolve the pull axis up front, before any rotation, so a malformed call
|
|
191
|
-
// fails before the
|
|
198
|
+
// fails before the descriptor is mutated.
|
|
192
199
|
const pullAxis = resolvePullAxis({ space, revoke, pull });
|
|
193
200
|
// 1. Read axis: mint a fresh epoch, wrap it to every remaining recipient,
|
|
194
201
|
// append it, and repoint `currentEpoch` (compare-and-swap, retried on race).
|
|
@@ -196,10 +203,10 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
196
203
|
// if the CAS keeps losing the race and throws, the reader is neither pulled
|
|
197
204
|
// nor rotated, so `removeRecipient` is safely retryable to convergence.
|
|
198
205
|
const { epochId, secret } = await mintEpoch();
|
|
199
|
-
const
|
|
200
|
-
store:
|
|
201
|
-
mutate: async (
|
|
202
|
-
const epochs =
|
|
206
|
+
const rotatedDescriptor = await casUpdateDescriptor({
|
|
207
|
+
store: descriptorStore,
|
|
208
|
+
mutate: async (descriptor) => {
|
|
209
|
+
const epochs = descriptor.epochs;
|
|
203
210
|
if (!epochs || epochs.length === 0) {
|
|
204
211
|
throw new ValidationError('Cannot removeRecipient: this collection has no key epochs.');
|
|
205
212
|
}
|
|
@@ -209,7 +216,7 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
209
216
|
// still present in that older epoch, so unioning would silently re-escrow
|
|
210
217
|
// it into the fresh epoch and hand it back read access. Older epochs exist
|
|
211
218
|
// only so existing readers can decrypt history.
|
|
212
|
-
const currentEpoch = epochs.find(epoch => epoch.id ===
|
|
219
|
+
const currentEpoch = epochs.find(epoch => epoch.id === descriptor.currentEpoch) ??
|
|
213
220
|
epochs[epochs.length - 1];
|
|
214
221
|
// Already excluded from the current epoch? A prior attempt's rotation
|
|
215
222
|
// landed (its revoke step then failed transiently and the caller
|
|
@@ -250,15 +257,15 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
250
257
|
recipients: newRecipients
|
|
251
258
|
};
|
|
252
259
|
// Re-authenticate the epoch configuration under the NEW epoch's secret
|
|
253
|
-
// (the rotating caller just minted it), computed over the exact
|
|
254
|
-
// being written so a CAS retry re-MACs the re-read
|
|
260
|
+
// (the rotating caller just minted it), computed over the exact descriptor
|
|
261
|
+
// being written so a CAS retry re-MACs the re-read descriptor state.
|
|
255
262
|
const next = {
|
|
256
|
-
...
|
|
263
|
+
...descriptor,
|
|
257
264
|
epochs: [...epochs, newEpoch],
|
|
258
265
|
currentEpoch: epochId
|
|
259
266
|
};
|
|
260
267
|
const epochsMac = await computeEpochsMac({
|
|
261
|
-
|
|
268
|
+
descriptor: next,
|
|
262
269
|
epochSecret: secret
|
|
263
270
|
});
|
|
264
271
|
return { ...next, epochsMac };
|
|
@@ -267,7 +274,7 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
267
274
|
// 2. Pull axis: withdraw the reader's server-side access AFTER the rotation
|
|
268
275
|
// is durable -- the default zcap revocation, or the caller-supplied `pull`.
|
|
269
276
|
await pullAxis();
|
|
270
|
-
return
|
|
277
|
+
return rotatedDescriptor;
|
|
271
278
|
}
|
|
272
279
|
/**
|
|
273
280
|
* Resolves the pull axis of {@link removeRecipient} -- exactly one of the
|
|
@@ -327,65 +334,65 @@ async function defaultResolveRecipientKey(kid) {
|
|
|
327
334
|
return { id: resolved.id, publicKeyMultibase: resolved.publicKeyMultibase };
|
|
328
335
|
}
|
|
329
336
|
/**
|
|
330
|
-
* Resolves the
|
|
337
|
+
* Resolves the descriptor store a recipient operation targets: the explicit
|
|
331
338
|
* `store`, or the Collection Description adapter over the `collection` sugar.
|
|
332
339
|
* Exactly one of the two must be supplied.
|
|
333
340
|
*
|
|
334
341
|
* @param options {object}
|
|
335
342
|
* @param [options.collection] {Collection}
|
|
336
|
-
* @param [options.store] {
|
|
337
|
-
* @returns {
|
|
343
|
+
* @param [options.store] {EncryptionDescriptorStore}
|
|
344
|
+
* @returns {EncryptionDescriptorStore}
|
|
338
345
|
*/
|
|
339
|
-
function
|
|
346
|
+
function descriptorStoreFor({ collection, store }) {
|
|
340
347
|
if (collection !== undefined && store !== undefined) {
|
|
341
348
|
throw new ValidationError('Pass either `collection` (the Collection Description hosts the ' +
|
|
342
|
-
'
|
|
349
|
+
'descriptor) or `store` (an explicit descriptor store), not both.');
|
|
343
350
|
}
|
|
344
351
|
if (store !== undefined) {
|
|
345
352
|
return store;
|
|
346
353
|
}
|
|
347
354
|
if (collection !== undefined) {
|
|
348
|
-
return
|
|
355
|
+
return collectionDescriptorStore({ collection });
|
|
349
356
|
}
|
|
350
|
-
throw new ValidationError('A recipient operation needs its
|
|
357
|
+
throw new ValidationError('A recipient operation needs its descriptor host: pass `collection` or ' +
|
|
351
358
|
'`store`.');
|
|
352
359
|
}
|
|
353
360
|
/**
|
|
354
|
-
* Reads the store's
|
|
355
|
-
* a compare-and-swap (`If-Match`). Retries on a stale (`412`) validator,
|
|
356
|
-
* re-reading the fresh
|
|
361
|
+
* Reads the store's descriptor, applies `mutate`, and writes the result back
|
|
362
|
+
* with a compare-and-swap (`If-Match`). Retries on a stale (`412`) validator,
|
|
363
|
+
* re-reading the fresh descriptor each time, up to {@link MAX_CAS_ATTEMPTS};
|
|
357
364
|
* surfaces {@link PreconditionFailedError} if it keeps losing the race. A
|
|
358
|
-
* `mutate` that resolves `null` signals "no change needed" (the
|
|
359
|
-
* reflects the desired state, e.g. an idempotent retry): nothing is
|
|
360
|
-
* and the current
|
|
365
|
+
* `mutate` that resolves `null` signals "no change needed" (the descriptor
|
|
366
|
+
* already reflects the desired state, e.g. an idempotent retry): nothing is
|
|
367
|
+
* written and the current descriptor is returned as-is.
|
|
361
368
|
*
|
|
362
|
-
* When the store reports no
|
|
369
|
+
* When the store reports no descriptor yet (`read()` resolves `null`, e.g. the
|
|
363
370
|
* resource adapter before the first `initRecipients`), the optional `seed` is
|
|
364
371
|
* mutated instead and the result written with the store's create-if-absent
|
|
365
372
|
* guard (`If-None-Match: *`). Only `initRecipients` passes a seed; without
|
|
366
|
-
* one an absent
|
|
367
|
-
* writer created the first
|
|
373
|
+
* one an absent descriptor is refused. Losing the create race (a concurrent
|
|
374
|
+
* writer created the first descriptor) re-enters the loop and re-reads, like a
|
|
368
375
|
* stale CAS.
|
|
369
376
|
*
|
|
370
377
|
* @param options {object}
|
|
371
|
-
* @param options.store {
|
|
372
|
-
* @param options.mutate {function}
|
|
378
|
+
* @param options.store {EncryptionDescriptorStore}
|
|
379
|
+
* @param options.mutate {function} descriptor to the next descriptor (may be async),
|
|
373
380
|
* or `null` to skip the write
|
|
374
|
-
* @param [options.seed] {CollectionEncryption} the
|
|
381
|
+
* @param [options.seed] {CollectionEncryption} the descriptor to mutate when the
|
|
375
382
|
* store holds none yet
|
|
376
|
-
* @returns {Promise<CollectionEncryption>} the written (or current)
|
|
383
|
+
* @returns {Promise<CollectionEncryption>} the written (or current) descriptor
|
|
377
384
|
*/
|
|
378
|
-
async function
|
|
385
|
+
async function casUpdateDescriptor({ store, mutate, seed }) {
|
|
379
386
|
let lastError;
|
|
380
387
|
for (let attempt = 0; attempt < MAX_CAS_ATTEMPTS; attempt++) {
|
|
381
388
|
const current = await store.read();
|
|
382
389
|
if (current === null) {
|
|
383
390
|
if (seed === undefined) {
|
|
384
|
-
throw new ValidationError('Cannot manage recipients: this
|
|
385
|
-
'
|
|
391
|
+
throw new ValidationError('Cannot manage recipients: this descriptor store holds no encryption ' +
|
|
392
|
+
'descriptor yet. Call initRecipients first.');
|
|
386
393
|
}
|
|
387
394
|
if (store.create === undefined) {
|
|
388
|
-
throw new ValidationError('Cannot initialize recipients: this
|
|
395
|
+
throw new ValidationError('Cannot initialize recipients: this descriptor store holds no descriptor ' +
|
|
389
396
|
'and does not support creating one.');
|
|
390
397
|
}
|
|
391
398
|
const created = await mutate(seed);
|
|
@@ -398,17 +405,18 @@ async function casUpdateMarker({ store, mutate, seed }) {
|
|
|
398
405
|
}
|
|
399
406
|
catch (err) {
|
|
400
407
|
if (err instanceof PreconditionFailedError) {
|
|
401
|
-
// A concurrent writer created the first
|
|
408
|
+
// A concurrent writer created the first descriptor: re-read and
|
|
409
|
+
// re-apply.
|
|
402
410
|
lastError = err;
|
|
403
411
|
continue;
|
|
404
412
|
}
|
|
405
413
|
throw err;
|
|
406
414
|
}
|
|
407
415
|
}
|
|
408
|
-
const next = await mutate(current.
|
|
416
|
+
const next = await mutate(current.descriptor);
|
|
409
417
|
if (next === null) {
|
|
410
|
-
// The
|
|
411
|
-
return current.
|
|
418
|
+
// The descriptor already reflects the desired state: nothing to write.
|
|
419
|
+
return current.descriptor;
|
|
412
420
|
}
|
|
413
421
|
try {
|
|
414
422
|
await store.replace(next, { ifMatch: current.etag });
|
|
@@ -424,7 +432,7 @@ async function casUpdateMarker({ store, mutate, seed }) {
|
|
|
424
432
|
}
|
|
425
433
|
}
|
|
426
434
|
throw new PreconditionFailedError(`Recipient change lost the compare-and-swap race after ${MAX_CAS_ATTEMPTS} ` +
|
|
427
|
-
'attempts (another writer kept updating the stored
|
|
435
|
+
'attempts (another writer kept updating the stored descriptor). ' +
|
|
428
436
|
'Retry the operation.', { cause: lastError });
|
|
429
437
|
}
|
|
430
438
|
//# sourceMappingURL=recipients.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"recipients.js","sourceRoot":"","sources":["../../src/edv/recipients.ts"],"names":[],"mappings":"AAmCA,OAAO,EAAE,uBAAuB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACvE,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"recipients.js","sourceRoot":"","sources":["../../src/edv/recipients.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
CHANGED
|
@@ -92,7 +92,7 @@ export declare class QuotaExceededError extends WasError {
|
|
|
92
92
|
}
|
|
93
93
|
/**
|
|
94
94
|
* A client-side, fail-closed encryption error: a collection is declared
|
|
95
|
-
* encrypted (by a per-handle override or its `encryption`
|
|
95
|
+
* encrypted (by a per-handle override or its `encryption` descriptor) but this
|
|
96
96
|
* client cannot build the codec -- no `encryption` provider is configured, or
|
|
97
97
|
* the keystore holds no keys for the collection (or does not handle its
|
|
98
98
|
* scheme). Raised before any request, so it carries no HTTP status; recover by
|
|
@@ -105,7 +105,7 @@ export declare class EncryptionError extends WasError {
|
|
|
105
105
|
/**
|
|
106
106
|
* A fail-closed key-epoch error: a reader could not unwrap any epoch key it
|
|
107
107
|
* needs to decrypt a resource on a multi-recipient encrypted Collection -- none
|
|
108
|
-
* of the
|
|
108
|
+
* of the descriptor's `recipients` entries yielded a key for this reader's
|
|
109
109
|
* key-agreement key (it was never a recipient, or has been removed and the
|
|
110
110
|
* epoch rotated). A subtype of {@link EncryptionError}, so existing
|
|
111
111
|
* `catch (EncryptionError)` fail-closed handling still catches it.
|
package/dist/errors.js
CHANGED
|
@@ -119,7 +119,7 @@ export class QuotaExceededError extends WasError {
|
|
|
119
119
|
}
|
|
120
120
|
/**
|
|
121
121
|
* A client-side, fail-closed encryption error: a collection is declared
|
|
122
|
-
* encrypted (by a per-handle override or its `encryption`
|
|
122
|
+
* encrypted (by a per-handle override or its `encryption` descriptor) but this
|
|
123
123
|
* client cannot build the codec -- no `encryption` provider is configured, or
|
|
124
124
|
* the keystore holds no keys for the collection (or does not handle its
|
|
125
125
|
* scheme). Raised before any request, so it carries no HTTP status; recover by
|
|
@@ -135,7 +135,7 @@ export class EncryptionError extends WasError {
|
|
|
135
135
|
/**
|
|
136
136
|
* A fail-closed key-epoch error: a reader could not unwrap any epoch key it
|
|
137
137
|
* needs to decrypt a resource on a multi-recipient encrypted Collection -- none
|
|
138
|
-
* of the
|
|
138
|
+
* of the descriptor's `recipients` entries yielded a key for this reader's
|
|
139
139
|
* key-agreement key (it was never a recipient, or has been removed and the
|
|
140
140
|
* epoch rotated). A subtype of {@link EncryptionError}, so existing
|
|
141
141
|
* `catch (EncryptionError)` fail-closed handling still catches it.
|
package/dist/internal/codec.d.ts
CHANGED
|
@@ -4,9 +4,9 @@ import type { EncryptionOverride, IZcap } from '../types.js';
|
|
|
4
4
|
/**
|
|
5
5
|
* A per-handle codec cache. Memoizes the in-flight resolution so concurrent
|
|
6
6
|
* callers share one round-trip, but drops it on rejection so a transient
|
|
7
|
-
* failure (e.g. a 500/network error during
|
|
7
|
+
* failure (e.g. a 500/network error during descriptor discovery) does not
|
|
8
8
|
* permanently poison the handle, and exposes `reset()` for when a handle's
|
|
9
|
-
* encryption state changes (e.g. `Collection.configure()` adds the
|
|
9
|
+
* encryption state changes (e.g. `Collection.configure()` adds the descriptor).
|
|
10
10
|
*/
|
|
11
11
|
export declare class CodecHolder {
|
|
12
12
|
#private;
|
|
@@ -57,20 +57,20 @@ export declare function collectionCodecHolder(context: ClientContext, options: {
|
|
|
57
57
|
*/
|
|
58
58
|
export declare const identityCodec: ResourceCodec;
|
|
59
59
|
/**
|
|
60
|
-
* Resolves the codec for a collection by deciding policy (override >
|
|
61
|
-
* plaintext) and then, when encrypted, building the encrypting codec from the
|
|
60
|
+
* Resolves the codec for a collection by deciding policy (override > descriptor
|
|
61
|
+
* > plaintext) and then, when encrypted, building the encrypting codec from the
|
|
62
62
|
* keystore. Fails closed: a collection declared encrypted (by override or
|
|
63
|
-
*
|
|
64
|
-
* than falling back to {@link identityCodec}.
|
|
63
|
+
* descriptor) for which no codec can be built throws {@link EncryptionError}
|
|
64
|
+
* rather than falling back to {@link identityCodec}.
|
|
65
65
|
*
|
|
66
66
|
* @param context {ClientContext}
|
|
67
67
|
* @param options {object}
|
|
68
68
|
* @param options.spaceId {string}
|
|
69
69
|
* @param options.collectionId {string}
|
|
70
70
|
* @param [options.override] {EncryptionOverride} per-handle override; wins
|
|
71
|
-
* over the
|
|
71
|
+
* over the descriptor and skips the descriptor read
|
|
72
72
|
* @param [options.capability] {IZcap} the handle's bound capability, used for
|
|
73
|
-
* the
|
|
73
|
+
* the descriptor-discovery describe (which happens only when there is no
|
|
74
74
|
* override and the client has a keystore)
|
|
75
75
|
* @returns {Promise<ResourceCodec>}
|
|
76
76
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/internal/codec.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"codec.d.ts","sourceRoot":"","sources":["../../src/internal/codec.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAgB,aAAa,EAAE,MAAM,aAAa,CAAA;AAC9D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAIjD,OAAO,KAAK,EAEV,kBAAkB,EAClB,KAAK,EAIN,MAAM,aAAa,CAAA;AAEpB;;;;;;GAMG;AACH,qBAAa,WAAW;;IAItB;;;OAGG;gBACS,OAAO,EAAE,MAAM,OAAO,CAAC,aAAa,CAAC;IAIjD;;;;OAIG;IACH,GAAG,IAAI,OAAO,CAAC,aAAa,CAAC;IAiB7B;;;;OAIG;IACH,KAAK,IAAI,IAAI;CAGd;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,aAAa,EACtB,OAAO,EAAE;IACP,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,GACA,WAAW,CAEb;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa,EAAE,aAoC3B,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,YAAY,CAChC,OAAO,EAAE,aAAa,EACtB,EACE,OAAO,EACP,YAAY,EACZ,QAAQ,EACR,UAAU,EACX,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,kBAAkB,CAAA;IAC7B,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,GACA,OAAO,CAAC,aAAa,CAAC,CA2DxB"}
|