@interop/was-client 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +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 +11 -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 +92 -30
- package/dist/edv/recipients.d.ts.map +1 -1
- package/dist/edv/recipients.js +228 -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
|
@@ -19,12 +19,13 @@
|
|
|
19
19
|
* URL-safe and never a reserved segment.
|
|
20
20
|
* - **Encrypted content type.** Documents are stored as `application/json` by
|
|
21
21
|
* default, so the profile works against an unmodified WAS server. The
|
|
22
|
-
* preferred
|
|
23
|
-
* which distinguishes EDV envelopes from plaintext
|
|
24
|
-
* listings and metadata -- but the server must register
|
|
25
|
-
* content-type parser to accept it (the reference
|
|
26
|
-
* server that does not will reject it with 415).
|
|
27
|
-
* JOSE_CONTENT_TYPE` to opt into it where the server
|
|
22
|
+
* preferred type is `application/jose+json` (exported as
|
|
23
|
+
* `JOSE_CONTENT_TYPE`), which distinguishes EDV envelopes from plaintext
|
|
24
|
+
* application JSON in listings and metadata -- but the server must register
|
|
25
|
+
* an `application/*+json` content-type parser to accept it (the reference
|
|
26
|
+
* was-teaching-server does; a server that does not will reject it with 415).
|
|
27
|
+
* Pass `contentType: JOSE_CONTENT_TYPE` to opt into it where the server
|
|
28
|
+
* supports it.
|
|
28
29
|
*
|
|
29
30
|
* Scope: documents (`insert` / `update` / `get`) plus blinded-index content
|
|
30
31
|
* query (`find`, the `blinded-index` profile of the reserved Collection
|
|
@@ -66,8 +67,8 @@ export declare class WasTransport extends Transport {
|
|
|
66
67
|
* @param options.collectionId {string} the vault Collection id
|
|
67
68
|
* @param [options.contentType] {string} content type for stored envelopes;
|
|
68
69
|
* defaults to `application/json` (accepted by an unmodified server). Pass
|
|
69
|
-
* `JOSE_CONTENT_TYPE` against a server that registers an
|
|
70
|
-
* parser.
|
|
70
|
+
* `JOSE_CONTENT_TYPE` against a server that registers an
|
|
71
|
+
* `application/*+json` parser.
|
|
71
72
|
*/
|
|
72
73
|
constructor({ was, spaceId, collectionId, contentType }: {
|
|
73
74
|
was: WasRequester;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C,OAAO,KAAK,EACV,SAAS,EACT,SAAS,EACT,kBAAkB,EACnB,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAUhD,OAAO,EAGL,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAsB5B;;;GAGG;AACH,KAAK,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AAqD9C,qBAAa,YAAa,SAAQ,SAAS;;IACzC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAK5B;;;;;;;;;OASG;gBACS,EACV,GAAG,EACH,OAAO,EACP,YAAY,EACZ,WAAkC,EACnC,EAAE;QACD,GAAG,EAAE,YAAY,CAAA;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB;IAwDD;;;;;;;;;;;;;;;;OAgBG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoC1D;;;;;;;;;;;;;;;;;;OAkBG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAmB1D;;;;;;;;;OASG;IACY,GAAG,CAAC,EACjB,EAAE,EACH,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IA0DrD;;;;;;;;;;;;;;;;;;;;OAoBG;IACY,IAAI,CAAC,EAAE,KAAK,EAAE,GAAE;QAAE,KAAK,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,MAAM,CAAC;IA6B3E;;;;;;;;;OASG;IACY,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;IAuB5C;;;;;;;;;;;;;;;;;;OAkBG;IACY,UAAU,CAAC,EACxB,KAAK,EACL,KAAK,EACN,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,SAAS,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B7D;;;;;;;;;;;;;;OAcG;IACY,QAAQ,CAAC,EACtB,KAAK,EACL,UAAU,EACX,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,SAAS,CAAC;CA6BrE"}
|
package/dist/edv/WasTransport.js
CHANGED
|
@@ -19,12 +19,13 @@
|
|
|
19
19
|
* URL-safe and never a reserved segment.
|
|
20
20
|
* - **Encrypted content type.** Documents are stored as `application/json` by
|
|
21
21
|
* default, so the profile works against an unmodified WAS server. The
|
|
22
|
-
* preferred
|
|
23
|
-
* which distinguishes EDV envelopes from plaintext
|
|
24
|
-
* listings and metadata -- but the server must register
|
|
25
|
-
* content-type parser to accept it (the reference
|
|
26
|
-
* server that does not will reject it with 415).
|
|
27
|
-
* JOSE_CONTENT_TYPE` to opt into it where the server
|
|
22
|
+
* preferred type is `application/jose+json` (exported as
|
|
23
|
+
* `JOSE_CONTENT_TYPE`), which distinguishes EDV envelopes from plaintext
|
|
24
|
+
* application JSON in listings and metadata -- but the server must register
|
|
25
|
+
* an `application/*+json` content-type parser to accept it (the reference
|
|
26
|
+
* was-teaching-server does; a server that does not will reject it with 415).
|
|
27
|
+
* Pass `contentType: JOSE_CONTENT_TYPE` to opt into it where the server
|
|
28
|
+
* supports it.
|
|
28
29
|
*
|
|
29
30
|
* Scope: documents (`insert` / `update` / `get`) plus blinded-index content
|
|
30
31
|
* query (`find`, the `blinded-index` profile of the reserved Collection
|
|
@@ -119,8 +120,8 @@ export class WasTransport extends Transport {
|
|
|
119
120
|
* @param options.collectionId {string} the vault Collection id
|
|
120
121
|
* @param [options.contentType] {string} content type for stored envelopes;
|
|
121
122
|
* defaults to `application/json` (accepted by an unmodified server). Pass
|
|
122
|
-
* `JOSE_CONTENT_TYPE` against a server that registers an
|
|
123
|
-
* parser.
|
|
123
|
+
* `JOSE_CONTENT_TYPE` against a server that registers an
|
|
124
|
+
* `application/*+json` parser.
|
|
124
125
|
*/
|
|
125
126
|
constructor({ was, spaceId, collectionId, contentType = DEFAULT_CONTENT_TYPE }) {
|
|
126
127
|
super();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"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"}
|
package/dist/edv/constants.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
/**
|
|
5
5
|
* Shared EDV-over-WAS constants: the stored-envelope content types (the portable
|
|
6
|
-
* default and the preferred JOSE
|
|
6
|
+
* default and the preferred JOSE type) and the envelope byte serialization.
|
|
7
7
|
* Kept in one place so `WasTransport` and `EdvCodec` stay in lockstep instead
|
|
8
8
|
* of each declaring their own copy.
|
|
9
9
|
*/
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The descriptor-store seam: where a `CollectionEncryption` descriptor lives
|
|
6
|
+
* and how it is compare-and-swapped. The recipient primitives (`initRecipients`
|
|
7
|
+
* / `addRecipient` / `removeRecipient`) mutate a descriptor only through this
|
|
8
|
+
* port, so the same key-epoch machinery manages a Collection's own `encryption`
|
|
9
|
+
* descriptor (the classic host) or a descriptor hosted as a plain JSON Resource
|
|
10
|
+
* (e.g. a per-user-key roster in a private collection).
|
|
11
|
+
*
|
|
12
|
+
* Two adapters:
|
|
13
|
+
*
|
|
14
|
+
* - {@link collectionDescriptorStore} -- the Collection Description's `encryption`
|
|
15
|
+
* member, read with `describeWithEtag` and written back with
|
|
16
|
+
* `replaceDescription` + `If-Match`. The server enforces the descriptor
|
|
17
|
+
* invariants (append-only epochs, monotone `currentEpoch`, non-decreasing
|
|
18
|
+
* `version`) on this path.
|
|
19
|
+
* - {@link resourceDescriptorStore} -- a descriptor stored verbatim as a JSON Resource.
|
|
20
|
+
* The server treats the resource as opaque content and enforces NO descriptor
|
|
21
|
+
* invariants there; integrity rests on the client-side `epochsMac` (verified
|
|
22
|
+
* by writers before encrypting) plus client-side epoch pinning. Both the
|
|
23
|
+
* compare-and-swap and the create-if-absent guard ride the backend's
|
|
24
|
+
* `conditional-writes` feature. The hosting collection must be plaintext: on
|
|
25
|
+
* an encrypted collection the EDV codec computes the write preconditions
|
|
26
|
+
* itself and the store's `ifMatch` would not be honored.
|
|
27
|
+
*/
|
|
28
|
+
import type { Collection } from '../Collection.js';
|
|
29
|
+
import type { Resource } from '../Resource.js';
|
|
30
|
+
import type { CollectionEncryption } from '../types.js';
|
|
31
|
+
/**
|
|
32
|
+
* Where a `CollectionEncryption` descriptor lives: a read-with-validator plus a
|
|
33
|
+
* compare-and-swap write, the two operations the recipient primitives' CAS loop
|
|
34
|
+
* needs. Implementations host the descriptor anywhere a versioned JSON value
|
|
35
|
+
* can live; the two shipped adapters are {@link collectionDescriptorStore} and
|
|
36
|
+
* {@link resourceDescriptorStore}.
|
|
37
|
+
*/
|
|
38
|
+
export interface EncryptionDescriptorStore {
|
|
39
|
+
/**
|
|
40
|
+
* Reads the current descriptor together with the opaque `etag` validator the
|
|
41
|
+
* next {@link replace} must be compare-and-swapped against. Resolves `null`
|
|
42
|
+
* when no descriptor exists yet AND this store can create one (the resource
|
|
43
|
+
* adapter before the first `initRecipients`); a store whose host must
|
|
44
|
+
* already exist (the description adapter) throws instead of resolving
|
|
45
|
+
* `null`. Throws when the hosted value is not an `edv`-scheme descriptor.
|
|
46
|
+
*
|
|
47
|
+
* @returns {Promise<{ descriptor: CollectionEncryption; etag?: string } | null>}
|
|
48
|
+
*/
|
|
49
|
+
read(): Promise<{
|
|
50
|
+
descriptor: CollectionEncryption;
|
|
51
|
+
etag?: string;
|
|
52
|
+
} | null>;
|
|
53
|
+
/**
|
|
54
|
+
* Replaces the descriptor, compare-and-swapped against `ifMatch` (the
|
|
55
|
+
* validator from {@link read}); a stale validator throws
|
|
56
|
+
* `PreconditionFailedError` (412). Must follow a {@link read} on the same
|
|
57
|
+
* store instance -- an adapter may forward sibling state observed by its most
|
|
58
|
+
* recent read (the description adapter forwards the description's `name` /
|
|
59
|
+
* `backend`).
|
|
60
|
+
*
|
|
61
|
+
* @param descriptor {CollectionEncryption}
|
|
62
|
+
* @param options {object}
|
|
63
|
+
* @param [options.ifMatch] {string} the validator from the prior read;
|
|
64
|
+
* absent against a host that does not version its writes
|
|
65
|
+
* @returns {Promise<void>}
|
|
66
|
+
*/
|
|
67
|
+
replace(descriptor: CollectionEncryption, options: {
|
|
68
|
+
ifMatch?: string;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Creates the FIRST descriptor where {@link read} resolved `null`, guarded
|
|
72
|
+
* create-if-absent (`If-None-Match: *`); throws `PreconditionFailedError`
|
|
73
|
+
* (412) when a concurrent writer created one first. Absent on stores whose
|
|
74
|
+
* host always exists (the description adapter).
|
|
75
|
+
*
|
|
76
|
+
* @param descriptor {CollectionEncryption}
|
|
77
|
+
* @returns {Promise<void>}
|
|
78
|
+
*/
|
|
79
|
+
create?(descriptor: CollectionEncryption): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The Collection Description adapter: the descriptor is the Description's
|
|
83
|
+
* `encryption` member. Read fails closed when the Description is unreadable
|
|
84
|
+
* (WAS masks unauthorized reads as 404) or the collection is not declared
|
|
85
|
+
* encrypted with the `edv` scheme; the CAS write forwards the description's
|
|
86
|
+
* sibling fields (`name` / `backend`) observed by the most recent read, so
|
|
87
|
+
* the replace-semantics PUT does not drop them. No `create`: a Collection
|
|
88
|
+
* Description always exists, so a first descriptor is declared via
|
|
89
|
+
* `collection.configure({ encryption })`, never through this store.
|
|
90
|
+
*
|
|
91
|
+
* @param options {object}
|
|
92
|
+
* @param options.collection {Collection}
|
|
93
|
+
* @returns {EncryptionDescriptorStore}
|
|
94
|
+
*/
|
|
95
|
+
export declare function collectionDescriptorStore({ collection }: {
|
|
96
|
+
collection: Collection;
|
|
97
|
+
}): EncryptionDescriptorStore;
|
|
98
|
+
/**
|
|
99
|
+
* The plain-JSON-Resource adapter: the descriptor is the resource's entire
|
|
100
|
+
* content, stored verbatim. Read resolves `null` when the resource is absent
|
|
101
|
+
* (the pre-`initRecipients` state -- `create` then writes the first descriptor
|
|
102
|
+
* with `If-None-Match: *`), and throws when the resource holds something other
|
|
103
|
+
* than an `edv`-scheme descriptor object.
|
|
104
|
+
*
|
|
105
|
+
* The server enforces no descriptor invariants on a resource (unlike a
|
|
106
|
+
* Collection Description): rollback/tamper detection rests on the descriptor's
|
|
107
|
+
* `epochsMac` and client-side epoch pinning, and the CAS/create guards ride the
|
|
108
|
+
* backend's `conditional-writes` feature. Host the resource in a plaintext
|
|
109
|
+
* collection -- on an encrypted collection the EDV codec computes the write
|
|
110
|
+
* preconditions itself, so this store's `ifMatch` would not be honored.
|
|
111
|
+
*
|
|
112
|
+
* @param options {object}
|
|
113
|
+
* @param options.resource {Resource}
|
|
114
|
+
* @returns {EncryptionDescriptorStore}
|
|
115
|
+
*/
|
|
116
|
+
export declare function resourceDescriptorStore({ resource }: {
|
|
117
|
+
resource: Resource;
|
|
118
|
+
}): EncryptionDescriptorStore;
|
|
119
|
+
//# sourceMappingURL=descriptorStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptorStore.d.ts","sourceRoot":"","sources":["../../src/edv/descriptorStore.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAA;AAClD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAG9C,OAAO,KAAK,EAEV,oBAAoB,EAErB,MAAM,aAAa,CAAA;AAEpB;;;;;;GAMG;AACH,MAAM,WAAW,yBAAyB;IACxC;;;;;;;;;OASG;IACH,IAAI,IAAI,OAAO,CAAC;QAAE,UAAU,EAAE,oBAAoB,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC,CAAA;IAE3E;;;;;;;;;;;;;OAaG;IACH,OAAO,CACL,UAAU,EAAE,oBAAoB,EAChC,OAAO,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAC5B,OAAO,CAAC,IAAI,CAAC,CAAA;IAEhB;;;;;;;;OAQG;IACH,MAAM,CAAC,CAAC,UAAU,EAAE,oBAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACzD;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CAAC,EACxC,UAAU,EACX,EAAE;IACD,UAAU,EAAE,UAAU,CAAA;CACvB,GAAG,yBAAyB,CAoC5B;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,QAAQ,EACT,EAAE;IACD,QAAQ,EAAE,QAAQ,CAAA;CACnB,GAAG,yBAAyB,CAgC5B"}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { unreadableDescriptionError } from '../internal/describe.js';
|
|
2
2
|
import { ValidationError } from '../errors.js';
|
|
3
3
|
/**
|
|
4
|
-
* The Collection Description adapter: the
|
|
4
|
+
* The Collection Description adapter: the descriptor is the Description's
|
|
5
5
|
* `encryption` member. Read fails closed when the Description is unreadable
|
|
6
6
|
* (WAS masks unauthorized reads as 404) or the collection is not declared
|
|
7
7
|
* encrypted with the `edv` scheme; the CAS write forwards the description's
|
|
8
8
|
* sibling fields (`name` / `backend`) observed by the most recent read, so
|
|
9
9
|
* the replace-semantics PUT does not drop them. No `create`: a Collection
|
|
10
|
-
* Description always exists, so a first
|
|
10
|
+
* Description always exists, so a first descriptor is declared via
|
|
11
11
|
* `collection.configure({ encryption })`, never through this store.
|
|
12
12
|
*
|
|
13
13
|
* @param options {object}
|
|
14
14
|
* @param options.collection {Collection}
|
|
15
|
-
* @returns {
|
|
15
|
+
* @returns {EncryptionDescriptorStore}
|
|
16
16
|
*/
|
|
17
|
-
export function
|
|
17
|
+
export function collectionDescriptorStore({ collection }) {
|
|
18
18
|
// The sibling description fields observed by the most recent read, forwarded
|
|
19
19
|
// verbatim by the CAS write (the server's replace semantics would otherwise
|
|
20
20
|
// drop them). Safe to forward even if stale: the write is pinned to the same
|
|
@@ -29,80 +29,81 @@ export function collectionMarkerStore({ collection }) {
|
|
|
29
29
|
advice: 'Use a capability that can read the Collection Description.'
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
const
|
|
33
|
-
if (!
|
|
32
|
+
const descriptor = current.description.encryption;
|
|
33
|
+
if (!descriptor || descriptor.scheme !== 'edv') {
|
|
34
34
|
throw new ValidationError('Cannot manage recipients: this collection is not declared ' +
|
|
35
35
|
"encrypted with the 'edv' scheme.");
|
|
36
36
|
}
|
|
37
37
|
described = current.description;
|
|
38
|
-
return {
|
|
38
|
+
return { descriptor, etag: current.etag };
|
|
39
39
|
},
|
|
40
|
-
async replace(
|
|
40
|
+
async replace(descriptor, { ifMatch }) {
|
|
41
41
|
await collection.replaceDescription({
|
|
42
42
|
name: described?.name,
|
|
43
43
|
backend: described?.backend,
|
|
44
|
-
encryption:
|
|
44
|
+
encryption: descriptor
|
|
45
45
|
}, { ifMatch });
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
/**
|
|
50
|
-
* The plain-JSON-Resource adapter: the
|
|
50
|
+
* The plain-JSON-Resource adapter: the descriptor is the resource's entire
|
|
51
51
|
* content, stored verbatim. Read resolves `null` when the resource is absent
|
|
52
|
-
* (the pre-`initRecipients` state -- `create` then writes the first
|
|
52
|
+
* (the pre-`initRecipients` state -- `create` then writes the first descriptor
|
|
53
53
|
* with `If-None-Match: *`), and throws when the resource holds something other
|
|
54
|
-
* than an `edv`-scheme
|
|
54
|
+
* than an `edv`-scheme descriptor object.
|
|
55
55
|
*
|
|
56
|
-
* The server enforces no
|
|
57
|
-
* Description): rollback/tamper detection rests on the
|
|
58
|
-
* and client-side epoch pinning, and the CAS/create guards ride the
|
|
59
|
-
* `conditional-writes` feature. Host the resource in a plaintext
|
|
60
|
-
* on an encrypted collection the EDV codec computes the write
|
|
61
|
-
* itself, so this store's `ifMatch` would not be honored.
|
|
56
|
+
* The server enforces no descriptor invariants on a resource (unlike a
|
|
57
|
+
* Collection Description): rollback/tamper detection rests on the descriptor's
|
|
58
|
+
* `epochsMac` and client-side epoch pinning, and the CAS/create guards ride the
|
|
59
|
+
* backend's `conditional-writes` feature. Host the resource in a plaintext
|
|
60
|
+
* collection -- on an encrypted collection the EDV codec computes the write
|
|
61
|
+
* preconditions itself, so this store's `ifMatch` would not be honored.
|
|
62
62
|
*
|
|
63
63
|
* @param options {object}
|
|
64
64
|
* @param options.resource {Resource}
|
|
65
|
-
* @returns {
|
|
65
|
+
* @returns {EncryptionDescriptorStore}
|
|
66
66
|
*/
|
|
67
|
-
export function
|
|
67
|
+
export function resourceDescriptorStore({ resource }) {
|
|
68
68
|
return {
|
|
69
69
|
async read() {
|
|
70
70
|
const current = await resource.getWithEtag();
|
|
71
71
|
if (current === null) {
|
|
72
72
|
return null;
|
|
73
73
|
}
|
|
74
|
-
const
|
|
75
|
-
if (
|
|
76
|
-
typeof
|
|
77
|
-
Array.isArray(
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
const descriptor = current.data;
|
|
75
|
+
if (descriptor === null ||
|
|
76
|
+
typeof descriptor !== 'object' ||
|
|
77
|
+
Array.isArray(descriptor) ||
|
|
78
|
+
descriptor instanceof Blob ||
|
|
79
|
+
descriptor.scheme !== 'edv') {
|
|
80
80
|
throw new ValidationError(`Cannot manage recipients: the resource "${resource.id}" does not ` +
|
|
81
|
-
"hold a CollectionEncryption
|
|
81
|
+
"hold a CollectionEncryption descriptor with the 'edv' scheme.");
|
|
82
82
|
}
|
|
83
83
|
return {
|
|
84
|
-
|
|
84
|
+
descriptor: descriptor,
|
|
85
85
|
etag: current.etag
|
|
86
86
|
};
|
|
87
87
|
},
|
|
88
|
-
async replace(
|
|
89
|
-
await resource.put(
|
|
88
|
+
async replace(descriptor, { ifMatch }) {
|
|
89
|
+
await resource.put(descriptorAsJson(descriptor), { ifMatch });
|
|
90
90
|
},
|
|
91
|
-
async create(
|
|
92
|
-
await resource.put(
|
|
91
|
+
async create(descriptor) {
|
|
92
|
+
await resource.put(descriptorAsJson(descriptor), { ifNoneMatch: true });
|
|
93
93
|
}
|
|
94
94
|
};
|
|
95
95
|
}
|
|
96
96
|
/**
|
|
97
|
-
* Casts a
|
|
98
|
-
* are interfaces without index signatures, so they do not structurally
|
|
99
|
-
* `JsonObject` -- but a
|
|
100
|
-
* through the Collection Description on the classic host), so this
|
|
97
|
+
* Casts a descriptor to the `JsonObject` a resource write takes. The descriptor
|
|
98
|
+
* types are interfaces without index signatures, so they do not structurally
|
|
99
|
+
* satisfy `JsonObject` -- but a descriptor is plain JSON by construction (it
|
|
100
|
+
* round-trips through the Collection Description on the classic host), so this
|
|
101
|
+
* is sound.
|
|
101
102
|
*
|
|
102
|
-
* @param
|
|
103
|
+
* @param descriptor {CollectionEncryption}
|
|
103
104
|
* @returns {JsonObject}
|
|
104
105
|
*/
|
|
105
|
-
function
|
|
106
|
-
return
|
|
106
|
+
function descriptorAsJson(descriptor) {
|
|
107
|
+
return descriptor;
|
|
107
108
|
}
|
|
108
|
-
//# sourceMappingURL=
|
|
109
|
+
//# sourceMappingURL=descriptorStore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"descriptorStore.js","sourceRoot":"","sources":["../../src/edv/descriptorStore.ts"],"names":[],"mappings":"AA6BA,OAAO,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AA0D9C;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,yBAAyB,CAAC,EACxC,UAAU,EAGX;IACC,6EAA6E;IAC7E,4EAA4E;IAC5E,6EAA6E;IAC7E,yEAAyE;IACzE,IAAI,SAA4C,CAAA;IAChD,OAAO;QACL,KAAK,CAAC,IAAI;YACR,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,gBAAgB,EAAE,CAAA;YACnD,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,MAAM,0BAA0B,CAAC;oBAC/B,SAAS,EAAE,mBAAmB;oBAC9B,MAAM,EAAE,4DAA4D;iBACrE,CAAC,CAAA;YACJ,CAAC;YACD,MAAM,UAAU,GAAG,OAAO,CAAC,WAAW,CAAC,UAAU,CAAA;YACjD,IAAI,CAAC,UAAU,IAAI,UAAU,CAAC,MAAM,KAAK,KAAK,EAAE,CAAC;gBAC/C,MAAM,IAAI,eAAe,CACvB,4DAA4D;oBAC1D,kCAAkC,CACrC,CAAA;YACH,CAAC;YACD,SAAS,GAAG,OAAO,CAAC,WAAW,CAAA;YAC/B,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAA;QAC3C,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE;YACnC,MAAM,UAAU,CAAC,kBAAkB,CACjC;gBACE,IAAI,EAAE,SAAS,EAAE,IAAI;gBACrB,OAAO,EAAE,SAAS,EAAE,OAAO;gBAC3B,UAAU,EAAE,UAAU;aACvB,EACD,EAAE,OAAO,EAAE,CACZ,CAAA;QACH,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,uBAAuB,CAAC,EACtC,QAAQ,EAGT;IACC,OAAO;QACL,KAAK,CAAC,IAAI;YACR,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,CAAA;YAC5C,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAA;YACb,CAAC;YACD,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAA;YAC/B,IACE,UAAU,KAAK,IAAI;gBACnB,OAAO,UAAU,KAAK,QAAQ;gBAC9B,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC;gBACzB,UAAU,YAAY,IAAI;gBACzB,UAAmC,CAAC,MAAM,KAAK,KAAK,EACrD,CAAC;gBACD,MAAM,IAAI,eAAe,CACvB,2CAA2C,QAAQ,CAAC,EAAE,aAAa;oBACjE,+DAA+D,CAClE,CAAA;YACH,CAAC;YACD,OAAO;gBACL,UAAU,EAAE,UAA6C;gBACzD,IAAI,EAAE,OAAO,CAAC,IAAI;aACnB,CAAA;QACH,CAAC;QACD,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,OAAO,EAAE;YACnC,MAAM,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,EAAE,OAAO,EAAE,CAAC,CAAA;QAC/D,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,UAAU;YACrB,MAAM,QAAQ,CAAC,GAAG,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,CAAC,CAAA;QACzE,CAAC;KACF,CAAA;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,gBAAgB,CAAC,UAAgC;IACxD,OAAO,UAAmC,CAAA;AAC5C,CAAC"}
|
package/dist/edv/docCipher.d.ts
CHANGED
|
@@ -14,21 +14,22 @@
|
|
|
14
14
|
*
|
|
15
15
|
* A collection may be single-recipient (only the wallet's own key-agreement key
|
|
16
16
|
* reads it) or multi-recipient. Multi-recipient collections carry a
|
|
17
|
-
* `CollectionEncryption`
|
|
18
|
-
* key to every reader, writes encrypt under the
|
|
19
|
-
* removing a reader appends a fresh epoch that excludes it.
|
|
20
|
-
* **read** axis only: it turns a reader's own key-agreement
|
|
21
|
-
* into a cipher that encrypts under the current epoch
|
|
22
|
-
* reader still holds a key for.
|
|
17
|
+
* `CollectionEncryption` descriptor with key epochs: each epoch wraps one
|
|
18
|
+
* collection key to every reader, writes encrypt under the descriptor's
|
|
19
|
+
* `currentEpoch`, and removing a reader appends a fresh epoch that excludes it.
|
|
20
|
+
* This module is the **read** axis only: it turns a reader's own key-agreement
|
|
21
|
+
* key plus the descriptor into a cipher that encrypts under the current epoch
|
|
22
|
+
* and decrypts any epoch that reader still holds a key for.
|
|
23
23
|
*
|
|
24
|
-
* Rotation is prospective, never retroactive: appending an epoch does not
|
|
25
|
-
* existing resources, and because resource ids are content-derived they
|
|
26
|
-
* stable across a rotation. Reads stay tolerant of unstamped pre-epoch
|
|
27
|
-
* indefinitely -- an envelope encrypted straight to the key-agreement
|
|
28
|
-
* any epoch existed) always decrypts through the single-key path.
|
|
24
|
+
* Rotation is prospective, never retroactive: appending an epoch does not
|
|
25
|
+
* rewrite existing resources, and because resource ids are content-derived they
|
|
26
|
+
* stay stable across a rotation. Reads stay tolerant of unstamped pre-epoch
|
|
27
|
+
* resources indefinitely -- an envelope encrypted straight to the key-agreement
|
|
28
|
+
* key (before any epoch existed) always decrypts through the single-key path.
|
|
29
29
|
*
|
|
30
|
-
* Runtime note (React Native): this exercises the cipher's AES-KW (with a
|
|
31
|
-
* Hermes fallback) and `TextDecoder`; both must be present on the
|
|
30
|
+
* Runtime note (React Native): this exercises the cipher's AES-KW (with a
|
|
31
|
+
* pure-JS Hermes fallback) and `TextDecoder`; both must be present on the
|
|
32
|
+
* device.
|
|
32
33
|
*/
|
|
33
34
|
import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
|
|
34
35
|
import type { CollectionEncryption } from '../types.js';
|
|
@@ -42,9 +43,9 @@ export type { DocCipher } from '../sync/types.js';
|
|
|
42
43
|
* -- on an epoch-aware cipher -- any epoch this cipher knows about. It signals
|
|
43
44
|
* that the caller's cached Collection Description may be stale and should be
|
|
44
45
|
* re-read before retrying: an epoch rotation emits no change-feed entry, so a
|
|
45
|
-
* cipher built from a pre-rotation
|
|
46
|
-
* epoch it has never seen. It also fires on a single-key cipher that
|
|
47
|
-
* envelope encrypted to a different key-agreement key entirely.
|
|
46
|
+
* cipher built from a pre-rotation descriptor meets envelopes stamped with a
|
|
47
|
+
* newer epoch it has never seen. It also fires on a single-key cipher that
|
|
48
|
+
* meets an envelope encrypted to a different key-agreement key entirely.
|
|
48
49
|
*/
|
|
49
50
|
export declare class UnknownEpochError extends Error {
|
|
50
51
|
constructor({ collectionId, kids }: {
|
|
@@ -55,10 +56,11 @@ export declare class UnknownEpochError extends Error {
|
|
|
55
56
|
/**
|
|
56
57
|
* A wallet's own key-agreement key as a `RecipientPublicKey` -- the "recipient
|
|
57
58
|
* zero" entry a caller passes to `initRecipients` when it first makes a
|
|
58
|
-
* collection multi-recipient (the owner must be a recipient of every epoch, or
|
|
59
|
-
* could write envelopes it cannot itself read). An
|
|
60
|
-
* carries a did:key-shaped `id` and a
|
|
61
|
-
* fragment resolves through the default
|
|
59
|
+
* collection multi-recipient (the owner must be a recipient of every epoch, or
|
|
60
|
+
* it could write envelopes it cannot itself read). An
|
|
61
|
+
* `X25519KeyAgreementKey2020` carries a did:key-shaped `id` and a
|
|
62
|
+
* `publicKeyMultibase`, so its `kid`'s fragment resolves through the default
|
|
63
|
+
* did:key recipient resolver.
|
|
62
64
|
*
|
|
63
65
|
* @param options {object}
|
|
64
66
|
* @param options.keyAgreementKey {IKeyAgreementKey}
|
|
@@ -78,15 +80,15 @@ export declare function ownerRecipient({ keyAgreementKey }: {
|
|
|
78
80
|
* id updated in place via `sequence` (the mutable head-document model, driven by
|
|
79
81
|
* `encryptUpdate`).
|
|
80
82
|
*
|
|
81
|
-
* With no `encryption`
|
|
82
|
-
* recipient: the key-agreement key encrypts and decrypts directly.
|
|
83
|
-
* the
|
|
84
|
-
* that encrypts every write under the
|
|
85
|
-
* epoch this reader still holds a key for. The
|
|
86
|
-
* either way, so a pre-epoch envelope keeps
|
|
87
|
-
* not a migration shim.
|
|
83
|
+
* With no `encryption` descriptor (or a descriptor with no epochs) the cipher
|
|
84
|
+
* is single- recipient: the key-agreement key encrypts and decrypts directly.
|
|
85
|
+
* With epochs on the descriptor the cipher becomes multi-recipient: it ALSO
|
|
86
|
+
* builds an epoch codec that encrypts every write under the descriptor's
|
|
87
|
+
* `currentEpoch` and decrypts any epoch this reader still holds a key for. The
|
|
88
|
+
* single-key codec stays built either way, so a pre-epoch envelope keeps
|
|
89
|
+
* decrypting -- a permanent tolerance, not a migration shim.
|
|
88
90
|
*
|
|
89
|
-
* The reader must be a recipient of every epoch on the
|
|
91
|
+
* The reader must be a recipient of every epoch on the descriptor (the owner is
|
|
90
92
|
* "recipient zero"). If it is a recipient of none, building the epoch codec
|
|
91
93
|
* throws {@link KeyUnwrapError}; this surfaces it with a clearer error rather
|
|
92
94
|
* than silently writing envelopes other recipients cannot read.
|
|
@@ -97,7 +99,7 @@ export declare function ownerRecipient({ keyAgreementKey }: {
|
|
|
97
99
|
* @param options.collectionId {string} labels errors; the codec is agnostic
|
|
98
100
|
* @param [options.idDerivation] {'content' | 'random'} defaults to `'content'`
|
|
99
101
|
* @param [options.encryption] {CollectionEncryption} the collection's
|
|
100
|
-
* encryption
|
|
102
|
+
* encryption descriptor; when it carries key epochs, the cipher becomes
|
|
101
103
|
* multi-recipient
|
|
102
104
|
* @returns {Promise<DocCipher>}
|
|
103
105
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"docCipher.d.ts","sourceRoot":"","sources":["../../src/edv/docCipher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"docCipher.d.ts","sourceRoot":"","sources":["../../src/edv/docCipher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACb,MAAM,8BAA8B,CAAA;AAErC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AACvD,OAAO,KAAK,EAAE,SAAS,EAAQ,MAAM,kBAAkB,CAAA;AAGvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAKzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AACzD,YAAY,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAA;AAEjD;;;;;;;;;GASG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;gBAC9B,EACV,YAAY,EACZ,IAAI,EACL,EAAE;QACD,YAAY,EAAE,MAAM,CAAA;QACpB,IAAI,EAAE,MAAM,EAAE,CAAA;KACf;CAUF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,EAC7B,eAAe,EAChB,EAAE;IACD,eAAe,EAAE,gBAAgB,CAAA;CAClC,GAAG,kBAAkB,CAcrB;AA8BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAsB,kBAAkB,CAAC,EACvC,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAwB,EACxB,UAAU,EACX,EAAE;IACD,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;IACzB,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAA;IACnC,UAAU,CAAC,EAAE,oBAAoB,CAAA;CAClC,GAAG,OAAO,CAAC,SAAS,CAAC,CA6JrB"}
|
package/dist/edv/docCipher.js
CHANGED
|
@@ -11,9 +11,9 @@ export { isEncryptedEnvelope } from '../sync/envelope.js';
|
|
|
11
11
|
* -- on an epoch-aware cipher -- any epoch this cipher knows about. It signals
|
|
12
12
|
* that the caller's cached Collection Description may be stale and should be
|
|
13
13
|
* re-read before retrying: an epoch rotation emits no change-feed entry, so a
|
|
14
|
-
* cipher built from a pre-rotation
|
|
15
|
-
* epoch it has never seen. It also fires on a single-key cipher that
|
|
16
|
-
* envelope encrypted to a different key-agreement key entirely.
|
|
14
|
+
* cipher built from a pre-rotation descriptor meets envelopes stamped with a
|
|
15
|
+
* newer epoch it has never seen. It also fires on a single-key cipher that
|
|
16
|
+
* meets an envelope encrypted to a different key-agreement key entirely.
|
|
17
17
|
*/
|
|
18
18
|
export class UnknownEpochError extends Error {
|
|
19
19
|
constructor({ collectionId, kids }) {
|
|
@@ -28,10 +28,11 @@ export class UnknownEpochError extends Error {
|
|
|
28
28
|
/**
|
|
29
29
|
* A wallet's own key-agreement key as a `RecipientPublicKey` -- the "recipient
|
|
30
30
|
* zero" entry a caller passes to `initRecipients` when it first makes a
|
|
31
|
-
* collection multi-recipient (the owner must be a recipient of every epoch, or
|
|
32
|
-
* could write envelopes it cannot itself read). An
|
|
33
|
-
* carries a did:key-shaped `id` and a
|
|
34
|
-
* fragment resolves through the default
|
|
31
|
+
* collection multi-recipient (the owner must be a recipient of every epoch, or
|
|
32
|
+
* it could write envelopes it cannot itself read). An
|
|
33
|
+
* `X25519KeyAgreementKey2020` carries a did:key-shaped `id` and a
|
|
34
|
+
* `publicKeyMultibase`, so its `kid`'s fragment resolves through the default
|
|
35
|
+
* did:key recipient resolver.
|
|
35
36
|
*
|
|
36
37
|
* @param options {object}
|
|
37
38
|
* @param options.keyAgreementKey {IKeyAgreementKey}
|
|
@@ -85,15 +86,15 @@ function envelopeRecipientKids(envelope) {
|
|
|
85
86
|
* id updated in place via `sequence` (the mutable head-document model, driven by
|
|
86
87
|
* `encryptUpdate`).
|
|
87
88
|
*
|
|
88
|
-
* With no `encryption`
|
|
89
|
-
* recipient: the key-agreement key encrypts and decrypts directly.
|
|
90
|
-
* the
|
|
91
|
-
* that encrypts every write under the
|
|
92
|
-
* epoch this reader still holds a key for. The
|
|
93
|
-
* either way, so a pre-epoch envelope keeps
|
|
94
|
-
* not a migration shim.
|
|
89
|
+
* With no `encryption` descriptor (or a descriptor with no epochs) the cipher
|
|
90
|
+
* is single- recipient: the key-agreement key encrypts and decrypts directly.
|
|
91
|
+
* With epochs on the descriptor the cipher becomes multi-recipient: it ALSO
|
|
92
|
+
* builds an epoch codec that encrypts every write under the descriptor's
|
|
93
|
+
* `currentEpoch` and decrypts any epoch this reader still holds a key for. The
|
|
94
|
+
* single-key codec stays built either way, so a pre-epoch envelope keeps
|
|
95
|
+
* decrypting -- a permanent tolerance, not a migration shim.
|
|
95
96
|
*
|
|
96
|
-
* The reader must be a recipient of every epoch on the
|
|
97
|
+
* The reader must be a recipient of every epoch on the descriptor (the owner is
|
|
97
98
|
* "recipient zero"). If it is a recipient of none, building the epoch codec
|
|
98
99
|
* throws {@link KeyUnwrapError}; this surfaces it with a clearer error rather
|
|
99
100
|
* than silently writing envelopes other recipients cannot read.
|
|
@@ -104,7 +105,7 @@ function envelopeRecipientKids(envelope) {
|
|
|
104
105
|
* @param options.collectionId {string} labels errors; the codec is agnostic
|
|
105
106
|
* @param [options.idDerivation] {'content' | 'random'} defaults to `'content'`
|
|
106
107
|
* @param [options.encryption] {CollectionEncryption} the collection's
|
|
107
|
-
* encryption
|
|
108
|
+
* encryption descriptor; when it carries key epochs, the cipher becomes
|
|
108
109
|
* multi-recipient
|
|
109
110
|
* @returns {Promise<DocCipher>}
|
|
110
111
|
*/
|
|
@@ -125,9 +126,9 @@ export async function createEdvDocCipher({ keyAgreementKey, keyResolver, collect
|
|
|
125
126
|
throw new Error(`Could not build the EDV cipher for collection "${collectionId}".`);
|
|
126
127
|
}
|
|
127
128
|
// On a multi-recipient collection, ALSO build the epoch codec: same provider
|
|
128
|
-
// and keys, but with the
|
|
129
|
-
// keys. Writes go under the
|
|
130
|
-
// matching the envelope's recipient kid.
|
|
129
|
+
// and keys, but with the descriptor so `codecFor` resolves this reader's
|
|
130
|
+
// per-epoch keys. Writes go under the descriptor's `currentEpoch`; reads pick
|
|
131
|
+
// the epoch key matching the envelope's recipient kid.
|
|
131
132
|
const hasEpochs = encryption?.epochs !== undefined && encryption.epochs.length > 0;
|
|
132
133
|
let epochCodec;
|
|
133
134
|
if (hasEpochs) {
|
|
@@ -173,9 +174,10 @@ export async function createEdvDocCipher({ keyAgreementKey, keyResolver, collect
|
|
|
173
174
|
};
|
|
174
175
|
return {
|
|
175
176
|
async encrypt({ data }) {
|
|
176
|
-
// `encode` with no caller id is the add() path: encrypt, then either
|
|
177
|
-
// and stamp the content-hash id (`'content'`) or use the minted
|
|
178
|
-
// Writes go under the current epoch on a multi-recipient
|
|
177
|
+
// `encode` with no caller id is the add() path: encrypt, then either
|
|
178
|
+
// derive and stamp the content-hash id (`'content'`) or use the minted
|
|
179
|
+
// random id. Writes go under the current epoch on a multi-recipient
|
|
180
|
+
// cipher.
|
|
179
181
|
const codec = epochCodec ?? directCodec;
|
|
180
182
|
const encoded = await codec.encode({
|
|
181
183
|
data: data
|
|
@@ -206,7 +208,7 @@ export async function createEdvDocCipher({ keyAgreementKey, keyResolver, collect
|
|
|
206
208
|
// direct codec (permanent tolerance, not a migration shim);
|
|
207
209
|
// 2. else, on an epoch cipher, any kid names a known epoch -- the epoch
|
|
208
210
|
// codec;
|
|
209
|
-
// 3. else UnknownEpochError: the
|
|
211
|
+
// 3. else UnknownEpochError: the descriptor is likely stale, or a single-key
|
|
210
212
|
// cipher met an envelope encrypted to a different key entirely.
|
|
211
213
|
const kids = envelopeRecipientKids(envelope);
|
|
212
214
|
const codec = selectCodec();
|
|
@@ -224,7 +226,7 @@ export async function createEdvDocCipher({ keyAgreementKey, keyResolver, collect
|
|
|
224
226
|
}
|
|
225
227
|
// A malformed/empty-kid envelope falls through to the direct codec so it
|
|
226
228
|
// can surface its own decrypt error; a non-empty set of unroutable kids
|
|
227
|
-
// is the stale-
|
|
229
|
+
// is the stale-descriptor signal.
|
|
228
230
|
if (kids.length === 0) {
|
|
229
231
|
return directCodec;
|
|
230
232
|
}
|