@interop/was-client 0.22.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 +8 -7
- package/dist/edv/index.d.ts.map +1 -1
- package/dist/edv/index.js +7 -6
- package/dist/edv/index.js.map +1 -1
- package/dist/edv/recipients.d.ts +31 -30
- package/dist/edv/recipients.d.ts.map +1 -1
- package/dist/edv/recipients.js +83 -80
- 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 +2 -2
- 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,23 +45,24 @@ 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,11 +70,11 @@ export interface OwnerKey {
|
|
|
69
70
|
* whose epoch key already exists (e.g. a per-user key being enrolled into
|
|
70
71
|
* its wrap-set roster). The `epochId` must be the key's did:key and `secret`
|
|
71
72
|
* its raw 32-byte private key, exactly what {@link mintEpoch} returns.
|
|
72
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
73
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
73
74
|
*/
|
|
74
75
|
export declare function initRecipients({ collection, store, recipients, epoch: premintedEpoch }: {
|
|
75
76
|
collection?: Collection;
|
|
76
|
-
store?:
|
|
77
|
+
store?: EncryptionDescriptorStore;
|
|
77
78
|
recipients: RecipientPublicKey[];
|
|
78
79
|
epoch?: {
|
|
79
80
|
epochId: string;
|
|
@@ -92,16 +93,16 @@ export declare function initRecipients({ collection, store, recipients, epoch: p
|
|
|
92
93
|
*
|
|
93
94
|
* @param options {object}
|
|
94
95
|
* @param [options.collection] {Collection} the collection whose Description
|
|
95
|
-
* hosts the
|
|
96
|
-
* @param [options.store] {
|
|
96
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
97
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
97
98
|
* @param options.recipient {RecipientPublicKey} the new reader's public KAK
|
|
98
99
|
* @param options.owner {OwnerKey} the caller's own key-agreement key, to
|
|
99
100
|
* unwrap each epoch key for re-wrapping to the new reader
|
|
100
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
101
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
101
102
|
*/
|
|
102
103
|
export declare function addRecipient({ collection, store, recipient, owner }: {
|
|
103
104
|
collection?: Collection;
|
|
104
|
-
store?:
|
|
105
|
+
store?: EncryptionDescriptorStore;
|
|
105
106
|
recipient: RecipientPublicKey;
|
|
106
107
|
owner: OwnerKey;
|
|
107
108
|
}): Promise<CollectionEncryption>;
|
|
@@ -137,8 +138,8 @@ export declare function addRecipient({ collection, store, recipient, owner }: {
|
|
|
137
138
|
*
|
|
138
139
|
* @param options {object}
|
|
139
140
|
* @param [options.collection] {Collection} the collection whose Description
|
|
140
|
-
* hosts the
|
|
141
|
-
* @param [options.store] {
|
|
141
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
142
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
142
143
|
* @param [options.space] {Space} the collection's Space, for the default
|
|
143
144
|
* pull axis (zcap revocation); required together with `revoke` unless a
|
|
144
145
|
* custom `pull` is supplied
|
|
@@ -158,11 +159,11 @@ export declare function addRecipient({ collection, store, recipient, owner }: {
|
|
|
158
159
|
* self-describing `did:key`. May resolve `null` to signal drop-this-kid:
|
|
159
160
|
* the rotation then excludes that entry from the fresh epoch instead of
|
|
160
161
|
* throwing (subject to the no-recipients-remaining guard).
|
|
161
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
162
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
162
163
|
*/
|
|
163
164
|
export declare function removeRecipient({ collection, store, space, recipientId, revoke, pull, resolveRecipientKey }: {
|
|
164
165
|
collection?: Collection;
|
|
165
|
-
store?:
|
|
166
|
+
store?: EncryptionDescriptorStore;
|
|
166
167
|
space?: Space;
|
|
167
168
|
recipientId: string;
|
|
168
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,23 +8,24 @@ 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,7 +33,7 @@ const MAX_CAS_ATTEMPTS = 3;
|
|
|
32
33
|
* whose epoch key already exists (e.g. a per-user key being enrolled into
|
|
33
34
|
* its wrap-set roster). The `epochId` must be the key's did:key and `secret`
|
|
34
35
|
* its raw 32-byte private key, exactly what {@link mintEpoch} returns.
|
|
35
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
36
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
36
37
|
*/
|
|
37
38
|
export async function initRecipients({ collection, store, recipients, epoch: premintedEpoch }) {
|
|
38
39
|
if (recipients.length === 0) {
|
|
@@ -43,29 +44,30 @@ export async function initRecipients({ collection, store, recipients, epoch: pre
|
|
|
43
44
|
id: epochId,
|
|
44
45
|
recipients: await Promise.all(recipients.map(recipient => wrapEpochSecret({ epochSecret: secret, recipient })))
|
|
45
46
|
};
|
|
46
|
-
return
|
|
47
|
-
store:
|
|
48
|
-
// A store whose
|
|
49
|
-
// (the create-if-absent branch); a Collection Description's
|
|
50
|
-
// 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.
|
|
51
52
|
seed: { scheme: 'edv' },
|
|
52
|
-
mutate: async (
|
|
53
|
-
if (
|
|
53
|
+
mutate: async (descriptor) => {
|
|
54
|
+
if (descriptor.epochs && descriptor.epochs.length > 0) {
|
|
54
55
|
throw new ValidationError('This collection already has key epochs; use addRecipient to add a ' +
|
|
55
56
|
'reader instead of initRecipients.');
|
|
56
57
|
}
|
|
57
|
-
// Declaring the first epochs, so stamp scheme version 1 when the
|
|
58
|
-
// does not already carry one, and authenticate the epoch
|
|
59
|
-
// with a MAC keyed from this first epoch's secret (computed
|
|
60
|
-
//
|
|
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).
|
|
61
63
|
const next = {
|
|
62
|
-
...
|
|
63
|
-
version:
|
|
64
|
+
...descriptor,
|
|
65
|
+
version: descriptor.version ?? 1,
|
|
64
66
|
epochs: [epoch],
|
|
65
67
|
currentEpoch: epochId
|
|
66
68
|
};
|
|
67
69
|
const epochsMac = await computeEpochsMac({
|
|
68
|
-
|
|
70
|
+
descriptor: next,
|
|
69
71
|
epochSecret: secret
|
|
70
72
|
});
|
|
71
73
|
return { ...next, epochsMac };
|
|
@@ -84,18 +86,18 @@ export async function initRecipients({ collection, store, recipients, epoch: pre
|
|
|
84
86
|
*
|
|
85
87
|
* @param options {object}
|
|
86
88
|
* @param [options.collection] {Collection} the collection whose Description
|
|
87
|
-
* hosts the
|
|
88
|
-
* @param [options.store] {
|
|
89
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
90
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
89
91
|
* @param options.recipient {RecipientPublicKey} the new reader's public KAK
|
|
90
92
|
* @param options.owner {OwnerKey} the caller's own key-agreement key, to
|
|
91
93
|
* unwrap each epoch key for re-wrapping to the new reader
|
|
92
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
94
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
93
95
|
*/
|
|
94
96
|
export async function addRecipient({ collection, store, recipient, owner }) {
|
|
95
|
-
return
|
|
96
|
-
store:
|
|
97
|
-
mutate: async (
|
|
98
|
-
const epochs =
|
|
97
|
+
return casUpdateDescriptor({
|
|
98
|
+
store: descriptorStoreFor({ collection, store }),
|
|
99
|
+
mutate: async (descriptor) => {
|
|
100
|
+
const epochs = descriptor.epochs;
|
|
99
101
|
if (!epochs || epochs.length === 0) {
|
|
100
102
|
throw new ValidationError('Cannot addRecipient: this collection has no key epochs. Call ' +
|
|
101
103
|
'initRecipients first.');
|
|
@@ -131,7 +133,7 @@ export async function addRecipient({ collection, store, recipient, owner }) {
|
|
|
131
133
|
recipients: [...epoch.recipients, wrapped]
|
|
132
134
|
};
|
|
133
135
|
}));
|
|
134
|
-
return { ...
|
|
136
|
+
return { ...descriptor, epochs: nextEpochs };
|
|
135
137
|
}
|
|
136
138
|
});
|
|
137
139
|
}
|
|
@@ -167,8 +169,8 @@ export async function addRecipient({ collection, store, recipient, owner }) {
|
|
|
167
169
|
*
|
|
168
170
|
* @param options {object}
|
|
169
171
|
* @param [options.collection] {Collection} the collection whose Description
|
|
170
|
-
* hosts the
|
|
171
|
-
* @param [options.store] {
|
|
172
|
+
* hosts the descriptor; exactly one of `collection` / `store`
|
|
173
|
+
* @param [options.store] {EncryptionDescriptorStore} an explicit descriptor store
|
|
172
174
|
* @param [options.space] {Space} the collection's Space, for the default
|
|
173
175
|
* pull axis (zcap revocation); required together with `revoke` unless a
|
|
174
176
|
* custom `pull` is supplied
|
|
@@ -188,12 +190,12 @@ export async function addRecipient({ collection, store, recipient, owner }) {
|
|
|
188
190
|
* self-describing `did:key`. May resolve `null` to signal drop-this-kid:
|
|
189
191
|
* the rotation then excludes that entry from the fresh epoch instead of
|
|
190
192
|
* throwing (subject to the no-recipients-remaining guard).
|
|
191
|
-
* @returns {Promise<CollectionEncryption>} the new
|
|
193
|
+
* @returns {Promise<CollectionEncryption>} the new descriptor
|
|
192
194
|
*/
|
|
193
195
|
export async function removeRecipient({ collection, store, space, recipientId, revoke, pull, resolveRecipientKey = defaultResolveRecipientKey }) {
|
|
194
|
-
const
|
|
196
|
+
const descriptorStore = descriptorStoreFor({ collection, store });
|
|
195
197
|
// Resolve the pull axis up front, before any rotation, so a malformed call
|
|
196
|
-
// fails before the
|
|
198
|
+
// fails before the descriptor is mutated.
|
|
197
199
|
const pullAxis = resolvePullAxis({ space, revoke, pull });
|
|
198
200
|
// 1. Read axis: mint a fresh epoch, wrap it to every remaining recipient,
|
|
199
201
|
// append it, and repoint `currentEpoch` (compare-and-swap, retried on race).
|
|
@@ -201,10 +203,10 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
201
203
|
// if the CAS keeps losing the race and throws, the reader is neither pulled
|
|
202
204
|
// nor rotated, so `removeRecipient` is safely retryable to convergence.
|
|
203
205
|
const { epochId, secret } = await mintEpoch();
|
|
204
|
-
const
|
|
205
|
-
store:
|
|
206
|
-
mutate: async (
|
|
207
|
-
const epochs =
|
|
206
|
+
const rotatedDescriptor = await casUpdateDescriptor({
|
|
207
|
+
store: descriptorStore,
|
|
208
|
+
mutate: async (descriptor) => {
|
|
209
|
+
const epochs = descriptor.epochs;
|
|
208
210
|
if (!epochs || epochs.length === 0) {
|
|
209
211
|
throw new ValidationError('Cannot removeRecipient: this collection has no key epochs.');
|
|
210
212
|
}
|
|
@@ -214,7 +216,7 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
214
216
|
// still present in that older epoch, so unioning would silently re-escrow
|
|
215
217
|
// it into the fresh epoch and hand it back read access. Older epochs exist
|
|
216
218
|
// only so existing readers can decrypt history.
|
|
217
|
-
const currentEpoch = epochs.find(epoch => epoch.id ===
|
|
219
|
+
const currentEpoch = epochs.find(epoch => epoch.id === descriptor.currentEpoch) ??
|
|
218
220
|
epochs[epochs.length - 1];
|
|
219
221
|
// Already excluded from the current epoch? A prior attempt's rotation
|
|
220
222
|
// landed (its revoke step then failed transiently and the caller
|
|
@@ -255,15 +257,15 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
255
257
|
recipients: newRecipients
|
|
256
258
|
};
|
|
257
259
|
// Re-authenticate the epoch configuration under the NEW epoch's secret
|
|
258
|
-
// (the rotating caller just minted it), computed over the exact
|
|
259
|
-
// 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.
|
|
260
262
|
const next = {
|
|
261
|
-
...
|
|
263
|
+
...descriptor,
|
|
262
264
|
epochs: [...epochs, newEpoch],
|
|
263
265
|
currentEpoch: epochId
|
|
264
266
|
};
|
|
265
267
|
const epochsMac = await computeEpochsMac({
|
|
266
|
-
|
|
268
|
+
descriptor: next,
|
|
267
269
|
epochSecret: secret
|
|
268
270
|
});
|
|
269
271
|
return { ...next, epochsMac };
|
|
@@ -272,7 +274,7 @@ export async function removeRecipient({ collection, store, space, recipientId, r
|
|
|
272
274
|
// 2. Pull axis: withdraw the reader's server-side access AFTER the rotation
|
|
273
275
|
// is durable -- the default zcap revocation, or the caller-supplied `pull`.
|
|
274
276
|
await pullAxis();
|
|
275
|
-
return
|
|
277
|
+
return rotatedDescriptor;
|
|
276
278
|
}
|
|
277
279
|
/**
|
|
278
280
|
* Resolves the pull axis of {@link removeRecipient} -- exactly one of the
|
|
@@ -332,65 +334,65 @@ async function defaultResolveRecipientKey(kid) {
|
|
|
332
334
|
return { id: resolved.id, publicKeyMultibase: resolved.publicKeyMultibase };
|
|
333
335
|
}
|
|
334
336
|
/**
|
|
335
|
-
* Resolves the
|
|
337
|
+
* Resolves the descriptor store a recipient operation targets: the explicit
|
|
336
338
|
* `store`, or the Collection Description adapter over the `collection` sugar.
|
|
337
339
|
* Exactly one of the two must be supplied.
|
|
338
340
|
*
|
|
339
341
|
* @param options {object}
|
|
340
342
|
* @param [options.collection] {Collection}
|
|
341
|
-
* @param [options.store] {
|
|
342
|
-
* @returns {
|
|
343
|
+
* @param [options.store] {EncryptionDescriptorStore}
|
|
344
|
+
* @returns {EncryptionDescriptorStore}
|
|
343
345
|
*/
|
|
344
|
-
function
|
|
346
|
+
function descriptorStoreFor({ collection, store }) {
|
|
345
347
|
if (collection !== undefined && store !== undefined) {
|
|
346
348
|
throw new ValidationError('Pass either `collection` (the Collection Description hosts the ' +
|
|
347
|
-
'
|
|
349
|
+
'descriptor) or `store` (an explicit descriptor store), not both.');
|
|
348
350
|
}
|
|
349
351
|
if (store !== undefined) {
|
|
350
352
|
return store;
|
|
351
353
|
}
|
|
352
354
|
if (collection !== undefined) {
|
|
353
|
-
return
|
|
355
|
+
return collectionDescriptorStore({ collection });
|
|
354
356
|
}
|
|
355
|
-
throw new ValidationError('A recipient operation needs its
|
|
357
|
+
throw new ValidationError('A recipient operation needs its descriptor host: pass `collection` or ' +
|
|
356
358
|
'`store`.');
|
|
357
359
|
}
|
|
358
360
|
/**
|
|
359
|
-
* Reads the store's
|
|
360
|
-
* a compare-and-swap (`If-Match`). Retries on a stale (`412`) validator,
|
|
361
|
-
* 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};
|
|
362
364
|
* surfaces {@link PreconditionFailedError} if it keeps losing the race. A
|
|
363
|
-
* `mutate` that resolves `null` signals "no change needed" (the
|
|
364
|
-
* reflects the desired state, e.g. an idempotent retry): nothing is
|
|
365
|
-
* 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.
|
|
366
368
|
*
|
|
367
|
-
* When the store reports no
|
|
369
|
+
* When the store reports no descriptor yet (`read()` resolves `null`, e.g. the
|
|
368
370
|
* resource adapter before the first `initRecipients`), the optional `seed` is
|
|
369
371
|
* mutated instead and the result written with the store's create-if-absent
|
|
370
372
|
* guard (`If-None-Match: *`). Only `initRecipients` passes a seed; without
|
|
371
|
-
* one an absent
|
|
372
|
-
* 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
|
|
373
375
|
* stale CAS.
|
|
374
376
|
*
|
|
375
377
|
* @param options {object}
|
|
376
|
-
* @param options.store {
|
|
377
|
-
* @param options.mutate {function}
|
|
378
|
+
* @param options.store {EncryptionDescriptorStore}
|
|
379
|
+
* @param options.mutate {function} descriptor to the next descriptor (may be async),
|
|
378
380
|
* or `null` to skip the write
|
|
379
|
-
* @param [options.seed] {CollectionEncryption} the
|
|
381
|
+
* @param [options.seed] {CollectionEncryption} the descriptor to mutate when the
|
|
380
382
|
* store holds none yet
|
|
381
|
-
* @returns {Promise<CollectionEncryption>} the written (or current)
|
|
383
|
+
* @returns {Promise<CollectionEncryption>} the written (or current) descriptor
|
|
382
384
|
*/
|
|
383
|
-
async function
|
|
385
|
+
async function casUpdateDescriptor({ store, mutate, seed }) {
|
|
384
386
|
let lastError;
|
|
385
387
|
for (let attempt = 0; attempt < MAX_CAS_ATTEMPTS; attempt++) {
|
|
386
388
|
const current = await store.read();
|
|
387
389
|
if (current === null) {
|
|
388
390
|
if (seed === undefined) {
|
|
389
|
-
throw new ValidationError('Cannot manage recipients: this
|
|
390
|
-
'
|
|
391
|
+
throw new ValidationError('Cannot manage recipients: this descriptor store holds no encryption ' +
|
|
392
|
+
'descriptor yet. Call initRecipients first.');
|
|
391
393
|
}
|
|
392
394
|
if (store.create === undefined) {
|
|
393
|
-
throw new ValidationError('Cannot initialize recipients: this
|
|
395
|
+
throw new ValidationError('Cannot initialize recipients: this descriptor store holds no descriptor ' +
|
|
394
396
|
'and does not support creating one.');
|
|
395
397
|
}
|
|
396
398
|
const created = await mutate(seed);
|
|
@@ -403,17 +405,18 @@ async function casUpdateMarker({ store, mutate, seed }) {
|
|
|
403
405
|
}
|
|
404
406
|
catch (err) {
|
|
405
407
|
if (err instanceof PreconditionFailedError) {
|
|
406
|
-
// A concurrent writer created the first
|
|
408
|
+
// A concurrent writer created the first descriptor: re-read and
|
|
409
|
+
// re-apply.
|
|
407
410
|
lastError = err;
|
|
408
411
|
continue;
|
|
409
412
|
}
|
|
410
413
|
throw err;
|
|
411
414
|
}
|
|
412
415
|
}
|
|
413
|
-
const next = await mutate(current.
|
|
416
|
+
const next = await mutate(current.descriptor);
|
|
414
417
|
if (next === null) {
|
|
415
|
-
// The
|
|
416
|
-
return current.
|
|
418
|
+
// The descriptor already reflects the desired state: nothing to write.
|
|
419
|
+
return current.descriptor;
|
|
417
420
|
}
|
|
418
421
|
try {
|
|
419
422
|
await store.replace(next, { ifMatch: current.etag });
|
|
@@ -429,7 +432,7 @@ async function casUpdateMarker({ store, mutate, seed }) {
|
|
|
429
432
|
}
|
|
430
433
|
}
|
|
431
434
|
throw new PreconditionFailedError(`Recipient change lost the compare-and-swap race after ${MAX_CAS_ATTEMPTS} ` +
|
|
432
|
-
'attempts (another writer kept updating the stored
|
|
435
|
+
'attempts (another writer kept updating the stored descriptor). ' +
|
|
433
436
|
'Retry the operation.', { cause: lastError });
|
|
434
437
|
}
|
|
435
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"}
|