@interop/was-client 0.18.0 → 0.20.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 +88 -0
- package/dist/Collection.d.ts +1 -46
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +77 -79
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts +1 -51
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +55 -55
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts +1 -27
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +65 -65
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts +1 -12
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +15 -15
- package/dist/WasClient.js.map +1 -1
- package/dist/edv/EdvCodec.d.ts +1 -139
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +57 -58
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +1 -53
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +29 -29
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/docCipher.d.ts +111 -0
- package/dist/edv/docCipher.d.ts.map +1 -0
- package/dist/edv/docCipher.js +236 -0
- package/dist/edv/docCipher.js.map +1 -0
- package/dist/edv/epochKeys.js +2 -2
- package/dist/edv/epochKeys.js.map +1 -1
- package/dist/edv/index.d.ts +2 -0
- package/dist/edv/index.d.ts.map +1 -1
- package/dist/edv/index.js +1 -0
- package/dist/edv/index.js.map +1 -1
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +28 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/codec.d.ts +1 -2
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +10 -10
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/features.d.ts +1 -12
- package/dist/internal/features.d.ts.map +1 -1
- package/dist/internal/features.js +8 -8
- package/dist/internal/features.js.map +1 -1
- package/dist/internal/pagination.d.ts +1 -1
- package/dist/internal/pagination.js +1 -1
- package/dist/sync/cid.d.ts +31 -0
- package/dist/sync/cid.d.ts.map +1 -0
- package/dist/sync/cid.js +55 -0
- package/dist/sync/cid.js.map +1 -0
- package/dist/sync/envelope.d.ts +20 -0
- package/dist/sync/envelope.d.ts.map +1 -0
- package/dist/sync/envelope.js +17 -0
- package/dist/sync/envelope.js.map +1 -0
- package/dist/sync/index.d.ts +29 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +28 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/plaintextCipher.d.ts +16 -0
- package/dist/sync/plaintextCipher.d.ts.map +1 -0
- package/dist/sync/plaintextCipher.js +36 -0
- package/dist/sync/plaintextCipher.js.map +1 -0
- package/dist/sync/port.d.ts +78 -0
- package/dist/sync/port.d.ts.map +1 -0
- package/dist/sync/port.js +204 -0
- package/dist/sync/port.js.map +1 -0
- package/dist/sync/provisioning.d.ts +44 -0
- package/dist/sync/provisioning.d.ts.map +1 -0
- package/dist/sync/provisioning.js +46 -0
- package/dist/sync/provisioning.js.map +1 -0
- package/dist/sync/types.d.ts +166 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +2 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/package.json +10 -2
package/dist/edv/WasTransport.js
CHANGED
|
@@ -110,8 +110,8 @@ export class WasTransport extends Transport {
|
|
|
110
110
|
spaceId;
|
|
111
111
|
collectionId;
|
|
112
112
|
contentType;
|
|
113
|
-
|
|
114
|
-
|
|
113
|
+
#was;
|
|
114
|
+
#features;
|
|
115
115
|
/**
|
|
116
116
|
* @param options {object}
|
|
117
117
|
* @param options.was {WasClient} a WAS client holding the signer
|
|
@@ -124,15 +124,15 @@ export class WasTransport extends Transport {
|
|
|
124
124
|
*/
|
|
125
125
|
constructor({ was, spaceId, collectionId, contentType = DEFAULT_CONTENT_TYPE }) {
|
|
126
126
|
super();
|
|
127
|
-
this
|
|
127
|
+
this.#was = was;
|
|
128
128
|
this.spaceId = spaceId;
|
|
129
129
|
this.collectionId = collectionId;
|
|
130
130
|
this.contentType = contentType;
|
|
131
131
|
// The shared memoizing feature probe (see `BackendFeatures` for the
|
|
132
132
|
// definitive-vs-transient caching rules), reading this collection's
|
|
133
133
|
// "Collection Backend Selected" descriptor with a signed GET.
|
|
134
|
-
this
|
|
135
|
-
const response = await this.
|
|
134
|
+
this.#features = new BackendFeatures(async () => {
|
|
135
|
+
const response = await this.#was.request({
|
|
136
136
|
path: collectionBackend(this.spaceId, this.collectionId),
|
|
137
137
|
method: 'GET'
|
|
138
138
|
});
|
|
@@ -148,7 +148,7 @@ export class WasTransport extends Transport {
|
|
|
148
148
|
* @param id {string} the EDV document id (= WAS resource id)
|
|
149
149
|
* @returns {string}
|
|
150
150
|
*/
|
|
151
|
-
|
|
151
|
+
#resourcePath(id) {
|
|
152
152
|
return resourcePath(this.spaceId, this.collectionId, id);
|
|
153
153
|
}
|
|
154
154
|
/**
|
|
@@ -162,10 +162,10 @@ export class WasTransport extends Transport {
|
|
|
162
162
|
* conditional-write precondition)
|
|
163
163
|
* @returns {Promise<HttpResponse>}
|
|
164
164
|
*/
|
|
165
|
-
async
|
|
165
|
+
async #put(id, encrypted, headers = {}) {
|
|
166
166
|
const body = envelopeBytes(encrypted);
|
|
167
|
-
return this.
|
|
168
|
-
path: this
|
|
167
|
+
return this.#was.request({
|
|
168
|
+
path: this.#resourcePath(id),
|
|
169
169
|
method: 'PUT',
|
|
170
170
|
body,
|
|
171
171
|
headers: { 'content-type': this.contentType, ...headers }
|
|
@@ -192,9 +192,9 @@ export class WasTransport extends Transport {
|
|
|
192
192
|
if (!encrypted) {
|
|
193
193
|
throw new TypeError('"encrypted" is required.');
|
|
194
194
|
}
|
|
195
|
-
if (await this.
|
|
195
|
+
if (await this.#features.has('conditional-writes')) {
|
|
196
196
|
try {
|
|
197
|
-
await this
|
|
197
|
+
await this.#put(encrypted.id, encrypted, { 'if-none-match': '*' });
|
|
198
198
|
}
|
|
199
199
|
catch (err) {
|
|
200
200
|
mapTransportError(err, {
|
|
@@ -210,14 +210,14 @@ export class WasTransport extends Transport {
|
|
|
210
210
|
}
|
|
211
211
|
return;
|
|
212
212
|
}
|
|
213
|
-
if (await this
|
|
213
|
+
if (await this.#exists(encrypted.id)) {
|
|
214
214
|
throw namedError({
|
|
215
215
|
name: 'DuplicateError',
|
|
216
216
|
message: `A document with id "${encrypted.id}" already exists.`
|
|
217
217
|
});
|
|
218
218
|
}
|
|
219
219
|
try {
|
|
220
|
-
await this
|
|
220
|
+
await this.#put(encrypted.id, encrypted);
|
|
221
221
|
}
|
|
222
222
|
catch (err) {
|
|
223
223
|
mapTransportError(err, {
|
|
@@ -249,7 +249,7 @@ export class WasTransport extends Transport {
|
|
|
249
249
|
throw new TypeError('"encrypted" is required.');
|
|
250
250
|
}
|
|
251
251
|
try {
|
|
252
|
-
await this
|
|
252
|
+
await this.#put(encrypted.id, encrypted);
|
|
253
253
|
}
|
|
254
254
|
catch (err) {
|
|
255
255
|
mapTransportError(err, {
|
|
@@ -278,8 +278,8 @@ export class WasTransport extends Transport {
|
|
|
278
278
|
}
|
|
279
279
|
let response;
|
|
280
280
|
try {
|
|
281
|
-
response = await this.
|
|
282
|
-
path: this
|
|
281
|
+
response = await this.#was.request({
|
|
282
|
+
path: this.#resourcePath(id),
|
|
283
283
|
method: 'GET'
|
|
284
284
|
});
|
|
285
285
|
}
|
|
@@ -299,8 +299,8 @@ export class WasTransport extends Transport {
|
|
|
299
299
|
* @param what {string} the operation name, for the message
|
|
300
300
|
* @returns {Promise<void>}
|
|
301
301
|
*/
|
|
302
|
-
async
|
|
303
|
-
if (!(await this.
|
|
302
|
+
async #requireFeature(feature, what) {
|
|
303
|
+
if (!(await this.#features.has(feature))) {
|
|
304
304
|
throw namedError({
|
|
305
305
|
name: 'NotSupportedError',
|
|
306
306
|
message: `${what} is not supported: the collection's backend ` +
|
|
@@ -316,9 +316,9 @@ export class WasTransport extends Transport {
|
|
|
316
316
|
* @param id {string}
|
|
317
317
|
* @returns {Promise<boolean>}
|
|
318
318
|
*/
|
|
319
|
-
async
|
|
319
|
+
async #exists(id) {
|
|
320
320
|
try {
|
|
321
|
-
await this.
|
|
321
|
+
await this.#was.request({ path: this.#resourcePath(id), method: 'HEAD' });
|
|
322
322
|
return true;
|
|
323
323
|
}
|
|
324
324
|
catch (err) {
|
|
@@ -353,7 +353,7 @@ export class WasTransport extends Transport {
|
|
|
353
353
|
if (!query) {
|
|
354
354
|
throw new TypeError('"query" is required.');
|
|
355
355
|
}
|
|
356
|
-
await this
|
|
356
|
+
await this.#requireFeature('blinded-index-query', 'Blinded-index query');
|
|
357
357
|
// `returnDocuments` is a first-class `IEDVQuery` field, but the WAS profile
|
|
358
358
|
// has no ids-only mode, so it is dropped (whatever its value) and full
|
|
359
359
|
// documents come back -- the best-effort degradation `EdvClientCore.find`
|
|
@@ -361,7 +361,7 @@ export class WasTransport extends Transport {
|
|
|
361
361
|
const { returnDocuments: _returnDocuments, ...blindedQuery } = query;
|
|
362
362
|
let response;
|
|
363
363
|
try {
|
|
364
|
-
response = await this.
|
|
364
|
+
response = await this.#was.request({
|
|
365
365
|
path: collectionQuery(this.spaceId, this.collectionId),
|
|
366
366
|
method: 'POST',
|
|
367
367
|
json: { profile: 'blinded-index', ...blindedQuery }
|
|
@@ -405,7 +405,7 @@ export class WasTransport extends Transport {
|
|
|
405
405
|
* @param chunkIndex {number} the chunk's non-negative ordinal index
|
|
406
406
|
* @returns {string}
|
|
407
407
|
*/
|
|
408
|
-
|
|
408
|
+
#chunkPath(docId, chunkIndex) {
|
|
409
409
|
return resourceChunkPath(this.spaceId, this.collectionId, docId, chunkIndex);
|
|
410
410
|
}
|
|
411
411
|
/**
|
|
@@ -437,10 +437,10 @@ export class WasTransport extends Transport {
|
|
|
437
437
|
// Gate on the affordance before diagnosing a 404: against a server with no
|
|
438
438
|
// `/chunks/{n}` route at all, the 404 would otherwise be misreported as a
|
|
439
439
|
// missing parent document.
|
|
440
|
-
await this
|
|
440
|
+
await this.#requireFeature('chunked-streams', 'Chunked encrypted storage');
|
|
441
441
|
try {
|
|
442
|
-
await this.
|
|
443
|
-
path: this
|
|
442
|
+
await this.#was.request({
|
|
443
|
+
path: this.#chunkPath(docId, chunk.index),
|
|
444
444
|
method: 'PUT',
|
|
445
445
|
body: envelopeBytes(chunk),
|
|
446
446
|
headers: { 'content-type': CHUNK_CONTENT_TYPE }
|
|
@@ -481,11 +481,11 @@ export class WasTransport extends Transport {
|
|
|
481
481
|
// Gate on the affordance before diagnosing a 404: against a server with no
|
|
482
482
|
// `/chunks/{n}` route at all, the 404 would otherwise surface as a spurious
|
|
483
483
|
// missing-chunk (data corruption) report.
|
|
484
|
-
await this
|
|
484
|
+
await this.#requireFeature('chunked-streams', 'Chunked encrypted storage');
|
|
485
485
|
let response;
|
|
486
486
|
try {
|
|
487
|
-
response = await this.
|
|
488
|
-
path: this
|
|
487
|
+
response = await this.#was.request({
|
|
488
|
+
path: this.#chunkPath(docId, chunkIndex),
|
|
489
489
|
method: 'GET'
|
|
490
490
|
});
|
|
491
491
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAQ/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACb,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAE5B;;;;;;;;GAQG;AACH,MAAM,kBAAkB,GAAG,0BAA0B,CAAA;AAErD;;;;GAIG;AACH,MAAM,2BAA2B,GAC/B,0EAA0E;IAC1E,kBAAkB,CAAA;AAQpB;;;;;;;;;;GAUG;AACH,SAAS,UAAU,CAAC,EAClB,IAAI,EACJ,OAAO,EACP,KAAK,EAKN;IACC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;IACf,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,GAAG,CAAC,KAAK,GAAG,KAAK,CAAA;IACnB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,iBAAiB,CACxB,GAAY,EACZ,OAA0D;IAE1D,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAChE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IAC5C,CAAC;IACD,MAAM,GAAG,CAAA;AACX,CAAC;AAED,MAAM,OAAO,YAAa,SAAQ,SAAS;IAChC,OAAO,CAAQ;IACf,YAAY,CAAQ;IACpB,WAAW,CAAQ;
|
|
1
|
+
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA0CG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAQ/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AACzD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EACL,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACb,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACL,oBAAoB,EACpB,aAAa,EACb,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAE5B;;;;;;;;GAQG;AACH,MAAM,kBAAkB,GAAG,0BAA0B,CAAA;AAErD;;;;GAIG;AACH,MAAM,2BAA2B,GAC/B,0EAA0E;IAC1E,kBAAkB,CAAA;AAQpB;;;;;;;;;;GAUG;AACH,SAAS,UAAU,CAAC,EAClB,IAAI,EACJ,OAAO,EACP,KAAK,EAKN;IACC,MAAM,GAAG,GAAG,IAAI,KAAK,CAAC,OAAO,CAAC,CAAA;IAC9B,GAAG,CAAC,IAAI,GAAG,IAAI,CAAA;IACf,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,GAAG,CAAC,KAAK,GAAG,KAAK,CAAA;IACnB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,iBAAiB,CACxB,GAAY,EACZ,OAA0D;IAE1D,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAA;IAC9B,MAAM,KAAK,GAAG,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAChE,IAAI,KAAK,EAAE,CAAC;QACV,MAAM,UAAU,CAAC,EAAE,GAAG,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;IAC5C,CAAC;IACD,MAAM,GAAG,CAAA;AACX,CAAC;AAED,MAAM,OAAO,YAAa,SAAQ,SAAS;IAChC,OAAO,CAAQ;IACf,YAAY,CAAQ;IACpB,WAAW,CAAQ;IAEnB,IAAI,CAAc;IAClB,SAAS,CAAiB;IAEnC;;;;;;;;;OASG;IACH,YAAY,EACV,GAAG,EACH,OAAO,EACP,YAAY,EACZ,WAAW,GAAG,oBAAoB,EAMnC;QACC,KAAK,EAAE,CAAA;QACP,IAAI,CAAC,IAAI,GAAG,GAAG,CAAA;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QACtB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAA;QAChC,IAAI,CAAC,WAAW,GAAG,WAAW,CAAA;QAC9B,oEAAoE;QACpE,oEAAoE;QACpE,8DAA8D;QAC9D,IAAI,CAAC,SAAS,GAAG,IAAI,eAAe,CAAC,KAAK,IAAI,EAAE;YAC9C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;gBACvC,IAAI,EAAE,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC;gBACxD,MAAM,EAAE,KAAK;aACd,CAAC,CAAA;YACF,OAAO,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC/B,CAAC,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAU;QACtB,OAAO,YAAY,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,EAAE,CAAC,CAAA;IAC1D,CAAC;IAED;;;;;;;;;;OAUG;IACH,KAAK,CAAC,IAAI,CACR,EAAU,EACV,SAA6B,EAC7B,UAAkC,EAAE;QAEpC,MAAM,IAAI,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;YACvB,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;YAC5B,MAAM,EAAE,KAAK;YACb,IAAI;YACJ,OAAO,EAAE,EAAE,cAAc,EAAE,IAAI,CAAC,WAAW,EAAE,GAAG,OAAO,EAAE;SAC1D,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;;;;;;;;;OAgBG;IACM,KAAK,CAAC,MAAM,CAAC,EACpB,SAAS,KAC6B,EAAE;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAA;QACjD,CAAC;QACD,IAAI,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,EAAE,EAAE,eAAe,EAAE,GAAG,EAAE,CAAC,CAAA;YACpE,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,iBAAiB,CAAC,GAAG,EAAE;oBACrB,GAAG,EAAE;wBACH,IAAI,EAAE,gBAAgB;wBACtB,OAAO,EAAE,uBAAuB,SAAS,CAAC,EAAE,mBAAmB;qBAChE;oBACD,GAAG,EAAE;wBACH,IAAI,EAAE,gBAAgB;wBACtB,OAAO,EAAE,2BAA2B;qBACrC;iBACF,CAAC,CAAA;YACJ,CAAC;YACD,OAAM;QACR,CAAC;QACD,IAAI,MAAM,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;YACrC,MAAM,UAAU,CAAC;gBACf,IAAI,EAAE,gBAAgB;gBACtB,OAAO,EAAE,uBAAuB,SAAS,CAAC,EAAE,mBAAmB;aAChE,CAAC,CAAA;QACJ,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,GAAG,EAAE;gBACrB,GAAG,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,2BAA2B,EAAE;aACtE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACM,KAAK,CAAC,MAAM,CAAC,EACpB,SAAS,KAC6B,EAAE;QACxC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,MAAM,IAAI,SAAS,CAAC,0BAA0B,CAAC,CAAA;QACjD,CAAC;QACD,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,SAAS,CAAC,CAAA;QAC1C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,GAAG,EAAE;gBACrB,GAAG,EAAE;oBACH,IAAI,EAAE,mBAAmB;oBACzB,OAAO,EACL,iEAAiE;wBACjE,oDAAoD;iBACvD;gBACD,GAAG,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,2BAA2B,EAAE;aACtE,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACM,KAAK,CAAC,GAAG,CAAC,EACjB,EAAE,KACiB,EAAE;QACrB,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,MAAM,IAAI,SAAS,CAAC,mBAAmB,CAAC,CAAA;QAC1C,CAAC;QACD,IAAI,QAAsB,CAAA;QAC1B,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;gBACjC,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC;gBAC5B,MAAM,EAAE,KAAK;aACd,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,GAAG,EAAE;gBACrB,GAAG,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,qBAAqB,EAAE;aAC/D,CAAC,CAAA;QACJ,CAAC;QACD,OAAO,CAAC,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAuB,CAAA;IAC7D,CAAC;IAED;;;;;;;;OAQG;IACH,KAAK,CAAC,eAAe,CAAC,OAAe,EAAE,IAAY;QACjD,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACzC,MAAM,UAAU,CAAC;gBACf,IAAI,EAAE,mBAAmB;gBACzB,OAAO,EACL,GAAG,IAAI,8CAA8C;oBACrD,2BAA2B,OAAO,eAAe;aACpD,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,OAAO,CAAC,EAAU;QACtB,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;YACzE,OAAO,IAAI,CAAA;QACb,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,UAAU,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC5B,OAAO,KAAK,CAAA;YACd,CAAC;YACD,MAAM,GAAG,CAAA;QACX,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACM,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,KAA4B,EAAE;QACvD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAC7C,CAAC;QACD,MAAM,IAAI,CAAC,eAAe,CAAC,qBAAqB,EAAE,qBAAqB,CAAC,CAAA;QACxE,4EAA4E;QAC5E,uEAAuE;QACvE,0EAA0E;QAC1E,6BAA6B;QAC7B,MAAM,EAAE,eAAe,EAAE,gBAAgB,EAAE,GAAG,YAAY,EAAE,GAAG,KAAK,CAAA;QACpE,IAAI,QAAsB,CAAA;QAC1B,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;gBACjC,IAAI,EAAE,eAAe,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,CAAC;gBACtD,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,YAAY,EAAE;aACpD,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,GAAG,EAAE;gBACrB,GAAG,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,uBAAuB,EAAE;aACjE,CAAC,CAAA;QACJ,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAA;QAC3C,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;QAC5D,CAAC;QACD,OAAO,MAAM,CAAA;IACf,CAAC;IAED;;;;;;;;;OASG;IACM,KAAK,CAAC,WAAW;QACxB,MAAM,UAAU,CAAC;YACf,IAAI,EAAE,mBAAmB;YACzB,OAAO,EACL,oEAAoE;gBACpE,kEAAkE;gBAClE,4DAA4D;SAC/D,CAAC,CAAA;IACJ,CAAC;IAED;;;;;;;;OAQG;IACH,UAAU,CAAC,KAAa,EAAE,UAAkB;QAC1C,OAAO,iBAAiB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;IAC9E,CAAC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACM,KAAK,CAAC,UAAU,CAAC,EACxB,KAAK,EACL,KAAK,KACoC,EAAE;QAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAC7C,CAAC;QACD,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAC7C,CAAC;QACD,2EAA2E;QAC3E,0EAA0E;QAC1E,2BAA2B;QAC3B,MAAM,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,2BAA2B,CAAC,CAAA;QAC1E,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;gBACtB,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC;gBACzC,MAAM,EAAE,KAAK;gBACb,IAAI,EAAE,aAAa,CAAC,KAAK,CAAC;gBAC1B,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;aAChD,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,GAAG,EAAE;gBACrB,GAAG,EAAE;oBACH,IAAI,EAAE,eAAe;oBACrB,OAAO,EACL,sBAAsB,KAAK,CAAC,KAAK,wBAAwB;wBACzD,IAAI,KAAK,yDAAyD;iBACrE;aACF,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;IAED;;;;;;;;;;;;;;OAcG;IACM,KAAK,CAAC,QAAQ,CAAC,EACtB,KAAK,EACL,UAAU,KACiC,EAAE;QAC7C,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,MAAM,IAAI,SAAS,CAAC,sBAAsB,CAAC,CAAA;QAC7C,CAAC;QACD,IAAI,UAAU,KAAK,SAAS,EAAE,CAAC;YAC7B,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,CAAA;QAClD,CAAC;QACD,2EAA2E;QAC3E,4EAA4E;QAC5E,0CAA0C;QAC1C,MAAM,IAAI,CAAC,eAAe,CAAC,iBAAiB,EAAE,2BAA2B,CAAC,CAAA;QAC1E,IAAI,QAAsB,CAAA;QAC1B,IAAI,CAAC;YACH,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;gBACjC,IAAI,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,UAAU,CAAC;gBACxC,MAAM,EAAE,KAAK;aACd,CAAC,CAAA;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,iBAAiB,CAAC,GAAG,EAAE;gBACrB,GAAG,EAAE;oBACH,IAAI,EAAE,eAAe;oBACrB,OAAO,EAAE,SAAS,UAAU,iBAAiB,KAAK,cAAc;iBACjE;aACF,CAAC,CAAA;QACJ,CAAC;QACD,mEAAmE;QACnE,0EAA0E;QAC1E,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAc,CAAA;IACvD,CAAC;CACF"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* `createEdvDocCipher`: a per-collection encrypt/decrypt seam for an end-to-end
|
|
6
|
+
* encrypted collection, wrapping the same EDV codec the `WasClient` handles use
|
|
7
|
+
* but pointed at a local replica. A write encrypts the document into an EDV
|
|
8
|
+
* envelope (`{ id, sequence, jwe }`) whose id is content-derived (a hash of the
|
|
9
|
+
* JWE ciphertext, `idDerivation: 'content'`) or a stable random id
|
|
10
|
+
* (`'random'`); a read decrypts the stored envelope back. The envelope is what a
|
|
11
|
+
* replica holds and what replication ships verbatim, so the same bytes -- and
|
|
12
|
+
* the same content-derived id -- appear on every replica. The port never touches
|
|
13
|
+
* these keys.
|
|
14
|
+
*
|
|
15
|
+
* A collection may be single-recipient (only the wallet's own key-agreement key
|
|
16
|
+
* reads it) or multi-recipient. Multi-recipient collections carry a
|
|
17
|
+
* `CollectionEncryption` marker with key epochs: each epoch wraps one collection
|
|
18
|
+
* key to every reader, writes encrypt under the marker's `currentEpoch`, and
|
|
19
|
+
* removing a reader appends a fresh epoch that excludes it. This module is the
|
|
20
|
+
* **read** axis only: it turns a reader's own key-agreement key plus the marker
|
|
21
|
+
* into a cipher that encrypts under the current epoch and decrypts any epoch that
|
|
22
|
+
* reader still holds a key for.
|
|
23
|
+
*
|
|
24
|
+
* Rotation is prospective, never retroactive: appending an epoch does not rewrite
|
|
25
|
+
* existing resources, and because resource ids are content-derived they stay
|
|
26
|
+
* stable across a rotation. Reads stay tolerant of unstamped pre-epoch resources
|
|
27
|
+
* indefinitely -- an envelope encrypted straight to the key-agreement key (before
|
|
28
|
+
* any epoch existed) always decrypts through the single-key path.
|
|
29
|
+
*
|
|
30
|
+
* Runtime note (React Native): this exercises the cipher's AES-KW (with a pure-JS
|
|
31
|
+
* Hermes fallback) and `TextDecoder`; both must be present on the device.
|
|
32
|
+
*/
|
|
33
|
+
import type { IKeyAgreementKey, IKeyResolver } from '@interop/data-integrity-core';
|
|
34
|
+
import type { CollectionEncryption } from '../types.js';
|
|
35
|
+
import type { DocCipher } from '../sync/types.js';
|
|
36
|
+
import type { RecipientPublicKey } from './recipients.js';
|
|
37
|
+
export { isEncryptedEnvelope } from '../sync/envelope.js';
|
|
38
|
+
export type { DocCipher } from '../sync/types.js';
|
|
39
|
+
/**
|
|
40
|
+
* Thrown by a {@link DocCipher.decrypt} when a stored envelope names a JWE
|
|
41
|
+
* recipient (`kid`) this cipher cannot route: neither the key-agreement key nor
|
|
42
|
+
* -- on an epoch-aware cipher -- any epoch this cipher knows about. It signals
|
|
43
|
+
* that the caller's cached Collection Description may be stale and should be
|
|
44
|
+
* re-read before retrying: an epoch rotation emits no change-feed entry, so a
|
|
45
|
+
* cipher built from a pre-rotation marker meets envelopes stamped with a newer
|
|
46
|
+
* epoch it has never seen. It also fires on a single-key cipher that meets an
|
|
47
|
+
* envelope encrypted to a different key-agreement key entirely.
|
|
48
|
+
*/
|
|
49
|
+
export declare class UnknownEpochError extends Error {
|
|
50
|
+
constructor({ collectionId, kids }: {
|
|
51
|
+
collectionId: string;
|
|
52
|
+
kids: string[];
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* A wallet's own key-agreement key as a `RecipientPublicKey` -- the "recipient
|
|
57
|
+
* 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 it
|
|
59
|
+
* could write envelopes it cannot itself read). An `X25519KeyAgreementKey2020`
|
|
60
|
+
* carries a did:key-shaped `id` and a `publicKeyMultibase`, so its `kid`'s
|
|
61
|
+
* fragment resolves through the default did:key recipient resolver.
|
|
62
|
+
*
|
|
63
|
+
* @param options {object}
|
|
64
|
+
* @param options.keyAgreementKey {IKeyAgreementKey}
|
|
65
|
+
* @returns {RecipientPublicKey}
|
|
66
|
+
*/
|
|
67
|
+
export declare function ownerRecipient({ keyAgreementKey }: {
|
|
68
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
69
|
+
}): RecipientPublicKey;
|
|
70
|
+
/**
|
|
71
|
+
* Builds a {@link DocCipher} for one encrypted collection from a reader's key
|
|
72
|
+
* material (the key-agreement key + resolver). Keys are supplied directly (no
|
|
73
|
+
* keystore lookup).
|
|
74
|
+
*
|
|
75
|
+
* `idDerivation` selects the id model: `'content'` (default) makes every id a
|
|
76
|
+
* hash of the JWE ciphertext -- the stable, replica-independent primary key an
|
|
77
|
+
* immutable content-addressed collection needs; `'random'` mints a stable random
|
|
78
|
+
* id updated in place via `sequence` (the mutable head-document model, driven by
|
|
79
|
+
* `encryptUpdate`).
|
|
80
|
+
*
|
|
81
|
+
* With no `encryption` marker (or a marker with no epochs) the cipher is single-
|
|
82
|
+
* recipient: the key-agreement key encrypts and decrypts directly. With epochs on
|
|
83
|
+
* the marker the cipher becomes multi-recipient: it ALSO builds an epoch codec
|
|
84
|
+
* that encrypts every write under the marker's `currentEpoch` and decrypts any
|
|
85
|
+
* epoch this reader still holds a key for. The single-key codec stays built
|
|
86
|
+
* either way, so a pre-epoch envelope keeps decrypting -- a permanent tolerance,
|
|
87
|
+
* not a migration shim.
|
|
88
|
+
*
|
|
89
|
+
* The reader must be a recipient of every epoch on the marker (the owner is
|
|
90
|
+
* "recipient zero"). If it is a recipient of none, building the epoch codec
|
|
91
|
+
* throws {@link KeyUnwrapError}; this surfaces it with a clearer error rather
|
|
92
|
+
* than silently writing envelopes other recipients cannot read.
|
|
93
|
+
*
|
|
94
|
+
* @param options {object}
|
|
95
|
+
* @param options.keyAgreementKey {IKeyAgreementKey}
|
|
96
|
+
* @param options.keyResolver {IKeyResolver}
|
|
97
|
+
* @param options.collectionId {string} labels errors; the codec is agnostic
|
|
98
|
+
* @param [options.idDerivation] {'content' | 'random'} defaults to `'content'`
|
|
99
|
+
* @param [options.encryption] {CollectionEncryption} the collection's
|
|
100
|
+
* encryption marker; when it carries key epochs, the cipher becomes
|
|
101
|
+
* multi-recipient
|
|
102
|
+
* @returns {Promise<DocCipher>}
|
|
103
|
+
*/
|
|
104
|
+
export declare function createEdvDocCipher({ keyAgreementKey, keyResolver, collectionId, idDerivation, encryption }: {
|
|
105
|
+
keyAgreementKey: IKeyAgreementKey;
|
|
106
|
+
keyResolver: IKeyResolver;
|
|
107
|
+
collectionId: string;
|
|
108
|
+
idDerivation?: 'content' | 'random';
|
|
109
|
+
encryption?: CollectionEncryption;
|
|
110
|
+
}): Promise<DocCipher>;
|
|
111
|
+
//# sourceMappingURL=docCipher.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docCipher.d.ts","sourceRoot":"","sources":["../../src/edv/docCipher.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;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;;;;;;;;;;;GAWG;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,CA4JrB"}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { KeyUnwrapError } from '../errors.js';
|
|
2
|
+
import { createEdvEncryption } from './EdvCodec.js';
|
|
3
|
+
import { epochKeyIdFor } from './epochCrypto.js';
|
|
4
|
+
// `isEncryptedEnvelope` and the `DocCipher` interface live in the crypto-free
|
|
5
|
+
// `../sync` module; re-exported here so an encrypted-collection consumer that
|
|
6
|
+
// imports this subpath gets both without a second import.
|
|
7
|
+
export { isEncryptedEnvelope } from '../sync/envelope.js';
|
|
8
|
+
/**
|
|
9
|
+
* Thrown by a {@link DocCipher.decrypt} when a stored envelope names a JWE
|
|
10
|
+
* recipient (`kid`) this cipher cannot route: neither the key-agreement key nor
|
|
11
|
+
* -- on an epoch-aware cipher -- any epoch this cipher knows about. It signals
|
|
12
|
+
* that the caller's cached Collection Description may be stale and should be
|
|
13
|
+
* re-read before retrying: an epoch rotation emits no change-feed entry, so a
|
|
14
|
+
* cipher built from a pre-rotation marker meets envelopes stamped with a newer
|
|
15
|
+
* epoch it has never seen. It also fires on a single-key cipher that meets an
|
|
16
|
+
* envelope encrypted to a different key-agreement key entirely.
|
|
17
|
+
*/
|
|
18
|
+
export class UnknownEpochError extends Error {
|
|
19
|
+
constructor({ collectionId, kids }) {
|
|
20
|
+
super(`Cannot decrypt a resource in collection "${collectionId}": its ` +
|
|
21
|
+
`envelope names recipient key id(s) [${kids.join(', ')}] that match ` +
|
|
22
|
+
'neither the key-agreement key nor any known key epoch. The cached ' +
|
|
23
|
+
'Collection Description may be stale (an epoch rotation emits no ' +
|
|
24
|
+
'change-feed entry); re-read it and rebuild the cipher.');
|
|
25
|
+
this.name = 'UnknownEpochError';
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A wallet's own key-agreement key as a `RecipientPublicKey` -- the "recipient
|
|
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 it
|
|
32
|
+
* could write envelopes it cannot itself read). An `X25519KeyAgreementKey2020`
|
|
33
|
+
* carries a did:key-shaped `id` and a `publicKeyMultibase`, so its `kid`'s
|
|
34
|
+
* fragment resolves through the default did:key recipient resolver.
|
|
35
|
+
*
|
|
36
|
+
* @param options {object}
|
|
37
|
+
* @param options.keyAgreementKey {IKeyAgreementKey}
|
|
38
|
+
* @returns {RecipientPublicKey}
|
|
39
|
+
*/
|
|
40
|
+
export function ownerRecipient({ keyAgreementKey }) {
|
|
41
|
+
const { id } = keyAgreementKey;
|
|
42
|
+
const { publicKeyMultibase, type } = keyAgreementKey;
|
|
43
|
+
if (typeof id !== 'string' || typeof publicKeyMultibase !== 'string') {
|
|
44
|
+
throw new Error('Cannot build an owner recipient: the key-agreement key lacks an id or ' +
|
|
45
|
+
'publicKeyMultibase (a public X25519 key is required to wrap an epoch ' +
|
|
46
|
+
'key to it).');
|
|
47
|
+
}
|
|
48
|
+
return { id, publicKeyMultibase, type };
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Extracts the JWE recipient key ids (`kid`) an EDV envelope names. An epoch
|
|
52
|
+
* envelope carries one kid (the epoch key id); a single-recipient envelope
|
|
53
|
+
* carries the key-agreement key id. Returns `[]` for a malformed envelope, so
|
|
54
|
+
* routing falls through to letting a codec surface its own error.
|
|
55
|
+
*/
|
|
56
|
+
function envelopeRecipientKids(envelope) {
|
|
57
|
+
if (envelope === null || typeof envelope !== 'object') {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
const jwe = envelope.jwe;
|
|
61
|
+
if (jwe === null || typeof jwe !== 'object') {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
const recipients = jwe.recipients;
|
|
65
|
+
if (!Array.isArray(recipients)) {
|
|
66
|
+
return [];
|
|
67
|
+
}
|
|
68
|
+
const kids = [];
|
|
69
|
+
for (const recipient of recipients) {
|
|
70
|
+
const kid = recipient?.header?.kid;
|
|
71
|
+
if (typeof kid === 'string') {
|
|
72
|
+
kids.push(kid);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return kids;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Builds a {@link DocCipher} for one encrypted collection from a reader's key
|
|
79
|
+
* material (the key-agreement key + resolver). Keys are supplied directly (no
|
|
80
|
+
* keystore lookup).
|
|
81
|
+
*
|
|
82
|
+
* `idDerivation` selects the id model: `'content'` (default) makes every id a
|
|
83
|
+
* hash of the JWE ciphertext -- the stable, replica-independent primary key an
|
|
84
|
+
* immutable content-addressed collection needs; `'random'` mints a stable random
|
|
85
|
+
* id updated in place via `sequence` (the mutable head-document model, driven by
|
|
86
|
+
* `encryptUpdate`).
|
|
87
|
+
*
|
|
88
|
+
* With no `encryption` marker (or a marker with no epochs) the cipher is single-
|
|
89
|
+
* recipient: the key-agreement key encrypts and decrypts directly. With epochs on
|
|
90
|
+
* the marker the cipher becomes multi-recipient: it ALSO builds an epoch codec
|
|
91
|
+
* that encrypts every write under the marker's `currentEpoch` and decrypts any
|
|
92
|
+
* epoch this reader still holds a key for. The single-key codec stays built
|
|
93
|
+
* either way, so a pre-epoch envelope keeps decrypting -- a permanent tolerance,
|
|
94
|
+
* not a migration shim.
|
|
95
|
+
*
|
|
96
|
+
* The reader must be a recipient of every epoch on the marker (the owner is
|
|
97
|
+
* "recipient zero"). If it is a recipient of none, building the epoch codec
|
|
98
|
+
* throws {@link KeyUnwrapError}; this surfaces it with a clearer error rather
|
|
99
|
+
* than silently writing envelopes other recipients cannot read.
|
|
100
|
+
*
|
|
101
|
+
* @param options {object}
|
|
102
|
+
* @param options.keyAgreementKey {IKeyAgreementKey}
|
|
103
|
+
* @param options.keyResolver {IKeyResolver}
|
|
104
|
+
* @param options.collectionId {string} labels errors; the codec is agnostic
|
|
105
|
+
* @param [options.idDerivation] {'content' | 'random'} defaults to `'content'`
|
|
106
|
+
* @param [options.encryption] {CollectionEncryption} the collection's
|
|
107
|
+
* encryption marker; when it carries key epochs, the cipher becomes
|
|
108
|
+
* multi-recipient
|
|
109
|
+
* @returns {Promise<DocCipher>}
|
|
110
|
+
*/
|
|
111
|
+
export async function createEdvDocCipher({ keyAgreementKey, keyResolver, collectionId, idDerivation = 'content', encryption }) {
|
|
112
|
+
const provider = createEdvEncryption({
|
|
113
|
+
resolveKeys: async () => null,
|
|
114
|
+
idDerivation
|
|
115
|
+
});
|
|
116
|
+
// The direct (single-key) codec is always built: it decrypts pre-epoch
|
|
117
|
+
// envelopes and is the whole cipher for a single-recipient collection.
|
|
118
|
+
const directCodec = await provider.codecFor({
|
|
119
|
+
spaceId: 'local',
|
|
120
|
+
collectionId,
|
|
121
|
+
scheme: 'edv',
|
|
122
|
+
keys: { keyAgreementKey, keyResolver }
|
|
123
|
+
});
|
|
124
|
+
if (!directCodec) {
|
|
125
|
+
throw new Error(`Could not build the EDV cipher for collection "${collectionId}".`);
|
|
126
|
+
}
|
|
127
|
+
// On a multi-recipient collection, ALSO build the epoch codec: same provider
|
|
128
|
+
// and keys, but with the marker so `codecFor` resolves this reader's per-epoch
|
|
129
|
+
// keys. Writes go under the marker's `currentEpoch`; reads pick the epoch key
|
|
130
|
+
// matching the envelope's recipient kid.
|
|
131
|
+
const hasEpochs = encryption?.epochs !== undefined && encryption.epochs.length > 0;
|
|
132
|
+
let epochCodec;
|
|
133
|
+
if (hasEpochs) {
|
|
134
|
+
try {
|
|
135
|
+
epochCodec = await provider.codecFor({
|
|
136
|
+
spaceId: 'local',
|
|
137
|
+
collectionId,
|
|
138
|
+
scheme: 'edv',
|
|
139
|
+
encryption,
|
|
140
|
+
keys: { keyAgreementKey, keyResolver }
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
if (err instanceof KeyUnwrapError) {
|
|
145
|
+
throw new Error(`Cannot build the multi-recipient EDV cipher for collection ` +
|
|
146
|
+
`"${collectionId}": the key-agreement key is not a recipient of any ` +
|
|
147
|
+
'key epoch on this collection. The owner must be a recipient of ' +
|
|
148
|
+
'every epoch (recipient zero) before writing, or it would encrypt ' +
|
|
149
|
+
'envelopes it cannot itself read.', { cause: err });
|
|
150
|
+
}
|
|
151
|
+
throw err;
|
|
152
|
+
}
|
|
153
|
+
if (!epochCodec) {
|
|
154
|
+
throw new Error(`Could not build the multi-recipient EDV cipher for collection ` +
|
|
155
|
+
`"${collectionId}".`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const vaultKid = keyAgreementKey.id;
|
|
159
|
+
const knownEpochKids = new Set((encryption?.epochs ?? []).map(epoch => epochKeyIdFor(epoch.id)));
|
|
160
|
+
// Parses the codec's `EncodedWrite` (id + envelope body bytes) to the stored
|
|
161
|
+
// `{ id, envelope, epoch? }` shape. Shared by the create and update paths.
|
|
162
|
+
const readEncoded = (encoded) => {
|
|
163
|
+
if (typeof encoded.id !== 'string' ||
|
|
164
|
+
!(encoded.body instanceof Uint8Array)) {
|
|
165
|
+
throw new Error(`EDV encrypt for collection "${collectionId}" returned no id/envelope body.`);
|
|
166
|
+
}
|
|
167
|
+
const envelope = JSON.parse(new TextDecoder().decode(encoded.body));
|
|
168
|
+
return {
|
|
169
|
+
id: encoded.id,
|
|
170
|
+
envelope,
|
|
171
|
+
...(typeof encoded.epoch === 'string' && { epoch: encoded.epoch })
|
|
172
|
+
};
|
|
173
|
+
};
|
|
174
|
+
return {
|
|
175
|
+
async encrypt({ data }) {
|
|
176
|
+
// `encode` with no caller id is the add() path: encrypt, then either derive
|
|
177
|
+
// and stamp the content-hash id (`'content'`) or use the minted random id.
|
|
178
|
+
// Writes go under the current epoch on a multi-recipient cipher.
|
|
179
|
+
const codec = epochCodec ?? directCodec;
|
|
180
|
+
const encoded = await codec.encode({
|
|
181
|
+
data: data
|
|
182
|
+
});
|
|
183
|
+
return readEncoded(encoded);
|
|
184
|
+
},
|
|
185
|
+
async encryptUpdate({ id, data, current }) {
|
|
186
|
+
// The update path (mutable random-id head document): hand the codec the
|
|
187
|
+
// prior stored envelope so it advances `sequence` from it and re-encrypts
|
|
188
|
+
// under the same id.
|
|
189
|
+
const codec = epochCodec ?? directCodec;
|
|
190
|
+
const priorResponse = {
|
|
191
|
+
data: current,
|
|
192
|
+
json: async () => current,
|
|
193
|
+
headers: { get: () => null }
|
|
194
|
+
};
|
|
195
|
+
const encoded = await codec.encode({
|
|
196
|
+
id,
|
|
197
|
+
data: data,
|
|
198
|
+
current: priorResponse
|
|
199
|
+
});
|
|
200
|
+
const { id: encodedId, envelope } = readEncoded(encoded);
|
|
201
|
+
return { id: encodedId, envelope };
|
|
202
|
+
},
|
|
203
|
+
async decrypt({ envelope }) {
|
|
204
|
+
// Route by the envelope's JWE recipient kids:
|
|
205
|
+
// 1. any kid is the key-agreement key id -- a pre-epoch envelope, so the
|
|
206
|
+
// direct codec (permanent tolerance, not a migration shim);
|
|
207
|
+
// 2. else, on an epoch cipher, any kid names a known epoch -- the epoch
|
|
208
|
+
// codec;
|
|
209
|
+
// 3. else UnknownEpochError: the marker is likely stale, or a single-key
|
|
210
|
+
// cipher met an envelope encrypted to a different key entirely.
|
|
211
|
+
const kids = envelopeRecipientKids(envelope);
|
|
212
|
+
const codec = selectCodec();
|
|
213
|
+
const response = {
|
|
214
|
+
data: envelope,
|
|
215
|
+
json: async () => envelope
|
|
216
|
+
};
|
|
217
|
+
return (await codec.decode(response));
|
|
218
|
+
function selectCodec() {
|
|
219
|
+
if (kids.some(kid => kid === vaultKid)) {
|
|
220
|
+
return directCodec;
|
|
221
|
+
}
|
|
222
|
+
if (epochCodec && kids.some(kid => knownEpochKids.has(kid))) {
|
|
223
|
+
return epochCodec;
|
|
224
|
+
}
|
|
225
|
+
// A malformed/empty-kid envelope falls through to the direct codec so it
|
|
226
|
+
// can surface its own decrypt error; a non-empty set of unroutable kids
|
|
227
|
+
// is the stale-marker signal.
|
|
228
|
+
if (kids.length === 0) {
|
|
229
|
+
return directCodec;
|
|
230
|
+
}
|
|
231
|
+
throw new UnknownEpochError({ collectionId, kids });
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
//# sourceMappingURL=docCipher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"docCipher.js","sourceRoot":"","sources":["../../src/edv/docCipher.ts"],"names":[],"mappings":"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"}
|
package/dist/edv/epochKeys.js
CHANGED
|
@@ -34,7 +34,7 @@ export async function resolveEpochKeys({ encryption, keyAgreementKey }) {
|
|
|
34
34
|
// the newest epoch it holds -- defined deterministically as the LAST epoch in
|
|
35
35
|
// the marker's canonical `epochs` order that names this reader, never the
|
|
36
36
|
// incidental order in which secrets happened to unwrap. A reader that is not a
|
|
37
|
-
// recipient of `currentEpoch` is a removed/
|
|
37
|
+
// recipient of `currentEpoch` is a removed/archive reader whose writes the
|
|
38
38
|
// server rejects via its revoked zcap anyway; selecting a deterministic
|
|
39
39
|
// fallback here only keeps the local `writeEpoch`/`writeKey` well-defined
|
|
40
40
|
// instead of assuming the `epochs` array is append-ordered newest-last.
|
|
@@ -85,7 +85,7 @@ export async function resolveEpochKeys({ encryption, keyAgreementKey }) {
|
|
|
85
85
|
// the codec's kid-match filter needs no secret) and unwraps + reconstructs its
|
|
86
86
|
// epoch secret only on first decrypt naming it, caching the result. So a
|
|
87
87
|
// write-only handle -- or a reader that only ever touches current-epoch
|
|
88
|
-
// resources -- never pays the ECDH + KDF + key-unwrap for
|
|
88
|
+
// resources -- never pays the ECDH + KDF + key-unwrap for archive epochs it
|
|
89
89
|
// does not read.
|
|
90
90
|
const readKeys = [writeKey];
|
|
91
91
|
for (const epoch of namedEpochs) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"epochKeys.js","sourceRoot":"","sources":["../../src/edv/epochKeys.ts"],"names":[],"mappings":"AAmBA,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAK7D,OAAO,EACL,aAAa,EACb,uBAAuB,EACvB,iBAAiB,EAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAsB/C;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,EACrC,UAAU,EACV,eAAe,EAIhB;IACC,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAA;IAChC,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,OAAO,IAAI,CAAA;IACb,CAAC;IACD,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,oDAAoD;IACpD,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CACxC,KAAK,CAAC,UAAU,CAAC,IAAI,CACnB,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,KAAK,eAAe,CAAC,EAAE,CACzD,CACF,CAAA;IACD,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,cAAc,CACtB,oEAAoE;YAClE,+DAA+D;YAC/D,qEAAqE;YACrE,uCAAuC,CAC1C,CAAA;IACH,CAAC;IACD,8EAA8E;IAC9E,8EAA8E;IAC9E,0EAA0E;IAC1E,+EAA+E;IAC/E,
|
|
1
|
+
{"version":3,"file":"epochKeys.js","sourceRoot":"","sources":["../../src/edv/epochKeys.ts"],"names":[],"mappings":"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"}
|
package/dist/edv/index.d.ts
CHANGED
|
@@ -27,4 +27,6 @@ export { WasTransport, JOSE_CONTENT_TYPE } from './WasTransport.js';
|
|
|
27
27
|
export { initRecipients, addRecipient, removeRecipient } from './recipients.js';
|
|
28
28
|
export type { OwnerKey, RecipientPublicKey } from './recipients.js';
|
|
29
29
|
export { mintEpoch, epochKeyIdFor } from './epochCrypto.js';
|
|
30
|
+
export { createEdvDocCipher, ownerRecipient, UnknownEpochError, isEncryptedEnvelope } from './docCipher.js';
|
|
31
|
+
export type { DocCipher } from './docCipher.js';
|
|
30
32
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/edv/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC/E,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAC7D,YAAY,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAC/E,YAAY,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACnE,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,gBAAgB,CAAA;AACvB,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA"}
|
package/dist/edv/index.js
CHANGED
|
@@ -25,4 +25,5 @@ export { createEdvEncryption, EdvCodec } from './EdvCodec.js';
|
|
|
25
25
|
export { WasTransport, JOSE_CONTENT_TYPE } from './WasTransport.js';
|
|
26
26
|
export { initRecipients, addRecipient, removeRecipient } from './recipients.js';
|
|
27
27
|
export { mintEpoch, epochKeyIdFor } from './epochCrypto.js';
|
|
28
|
+
export { createEdvDocCipher, ownerRecipient, UnknownEpochError, isEncryptedEnvelope } from './docCipher.js';
|
|
28
29
|
//# sourceMappingURL=index.js.map
|
package/dist/edv/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE/E,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/edv/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACnE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAE/E,OAAO,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAC3D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACpB,MAAM,gBAAgB,CAAA"}
|