@interop/was-client 0.9.2 → 0.11.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 +32 -4
- package/dist/Collection.d.ts +49 -10
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +161 -61
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts +41 -12
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +87 -54
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts +1 -0
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +24 -27
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts +43 -2
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +90 -14
- package/dist/WasClient.js.map +1 -1
- package/dist/codec.d.ts +48 -9
- package/dist/codec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.d.ts +96 -37
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +245 -90
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +6 -12
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +6 -21
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/constants.d.ts +30 -0
- package/dist/edv/constants.d.ts.map +1 -0
- package/dist/edv/constants.js +30 -0
- package/dist/edv/constants.js.map +1 -0
- package/dist/edv/index.d.ts +1 -1
- package/dist/edv/index.d.ts.map +1 -1
- package/dist/edv/index.js +1 -1
- package/dist/edv/index.js.map +1 -1
- package/dist/errors.d.ts +3 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +15 -5
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/codec.d.ts +71 -5
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +102 -7
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/content.d.ts +74 -3
- package/dist/internal/content.d.ts.map +1 -1
- package/dist/internal/content.js +78 -7
- package/dist/internal/content.js.map +1 -1
- package/dist/internal/describe.d.ts.map +1 -1
- package/dist/internal/describe.js +2 -1
- package/dist/internal/describe.js.map +1 -1
- package/dist/internal/pagination.d.ts +45 -0
- package/dist/internal/pagination.d.ts.map +1 -0
- package/dist/internal/pagination.js +53 -0
- package/dist/internal/pagination.js.map +1 -0
- package/dist/internal/paths.d.ts +4 -0
- package/dist/internal/paths.d.ts.map +1 -1
- package/dist/internal/paths.js +10 -1
- package/dist/internal/paths.js.map +1 -1
- package/dist/internal/policy.d.ts +54 -0
- package/dist/internal/policy.d.ts.map +1 -0
- package/dist/internal/policy.js +58 -0
- package/dist/internal/policy.js.map +1 -0
- package/dist/internal/request.d.ts +4 -2
- package/dist/internal/request.d.ts.map +1 -1
- package/dist/internal/request.js +9 -2
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/reserved.d.ts +3 -8
- package/dist/internal/reserved.d.ts.map +1 -1
- package/dist/internal/reserved.js +10 -20
- package/dist/internal/reserved.js.map +1 -1
- package/dist/internal/write.d.ts +37 -0
- package/dist/internal/write.d.ts.map +1 -0
- package/dist/internal/write.js +29 -0
- package/dist/internal/write.js.map +1 -0
- package/dist/types.d.ts +14 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
package/dist/edv/EdvCodec.js
CHANGED
|
@@ -11,11 +11,11 @@
|
|
|
11
11
|
* app's `resolveKeys`; they never reach the server, which stores only opaque
|
|
12
12
|
* JWE envelopes.
|
|
13
13
|
*
|
|
14
|
-
* This reuses `EdvClientCore`'s
|
|
15
|
-
*
|
|
16
|
-
* the
|
|
17
|
-
* I/O, so the codec is a
|
|
18
|
-
* its own.
|
|
14
|
+
* This reuses `EdvClientCore`'s transport-free `documentCipher` (its public
|
|
15
|
+
* `EdvDocumentCipher` -- the same JWE machinery as the standalone
|
|
16
|
+
* `WasTransport`), but here the WAS Resource CRUD -- the transport role -- is
|
|
17
|
+
* played by core was-client's `Collection`/`Resource` I/O, so the codec is a
|
|
18
|
+
* pure encode/decode transform and needs no transport of its own.
|
|
19
19
|
*
|
|
20
20
|
* Scope (documents-only):
|
|
21
21
|
*
|
|
@@ -24,9 +24,12 @@
|
|
|
24
24
|
* a human-readable id is rejected (it would leak onto the URL). Carry a
|
|
25
25
|
* human-readable label inside the encrypted content instead. (Blind-derived
|
|
26
26
|
* ids are a deferred future item.)
|
|
27
|
-
* - **
|
|
28
|
-
* is
|
|
29
|
-
* (
|
|
27
|
+
* - **Inline non-JSON as a single JWE.** A `Blob`/`Uint8Array` under the size cap
|
|
28
|
+
* is encrypted as one document -- stored as a legible UTF-8 string for a
|
|
29
|
+
* text-family type (else base64) -- with the plaintext content type and the
|
|
30
|
+
* encoding carried in the document `meta`. An oversized one is
|
|
31
|
+
* rejected (large chunked encrypted blobs need the server's `chunked-streams`
|
|
32
|
+
* affordance).
|
|
30
33
|
* - **Enforced sequence (conditional writes).** The codec sets
|
|
31
34
|
* `conditionalWrites`, so the write path pre-reads the current envelope and
|
|
32
35
|
* hands it to `encode`: an update advances `sequence` from its prior value and
|
|
@@ -35,34 +38,31 @@
|
|
|
35
38
|
* surfaces as a `PreconditionFailedError` (412) -- the lost-update guard --
|
|
36
39
|
* rather than the old advisory last-writer-wins. Against a backend that does
|
|
37
40
|
* not advertise `conditional-writes` (no ETag) it degrades to advisory.
|
|
38
|
-
* - **
|
|
39
|
-
* `
|
|
40
|
-
*
|
|
41
|
+
* - **Encrypted metadata.** `metadataMode` is `'encrypted'`, so a Resource's
|
|
42
|
+
* user-writable `custom` (`name`/`tags`, via `setName`/`setTags`/`setMeta`) is
|
|
43
|
+
* encrypted into an EDV Document envelope with the same `documentCipher` used
|
|
44
|
+
* for content and stored opaquely under `/meta`; the server never sees
|
|
45
|
+
* plaintext `name`/`tags`. A reader with the keys decrypts it back
|
|
46
|
+
* transparently via `meta()`.
|
|
41
47
|
*/
|
|
42
48
|
import { EdvClientCore } from '@interop/edv-client';
|
|
43
|
-
import { ValidationError } from '../errors.js';
|
|
44
|
-
import { readJsonData } from '../internal/content.js';
|
|
45
|
-
import {
|
|
49
|
+
import { EncryptionError, ValidationError } from '../errors.js';
|
|
50
|
+
import { guessContentTypeFromId, isBlob, isTextContentType, readJsonData } from '../internal/content.js';
|
|
51
|
+
import { DEFAULT_CONTENT_TYPE, ENCODER } from './constants.js';
|
|
46
52
|
/**
|
|
47
|
-
* Default ceiling for a single-document (unchunked) encrypted binary
|
|
48
|
-
* Past this a `Blob`/`Uint8Array` is
|
|
49
|
-
* supported.
|
|
53
|
+
* Default ceiling for a single-document (unchunked) encrypted binary or text
|
|
54
|
+
* write, measured in raw (pre-base64) bytes. Past this a `Blob`/`Uint8Array` is
|
|
55
|
+
* rejected until chunked encrypted blobs are supported. 5 MiB; binary inflates
|
|
56
|
+
* ~33% under base64, text is stored verbatim.
|
|
50
57
|
*/
|
|
51
|
-
const DEFAULT_MAX_BLOB_BYTES = 1024 * 1024;
|
|
58
|
+
const DEFAULT_MAX_BLOB_BYTES = 5 * 1024 * 1024;
|
|
52
59
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
* `
|
|
56
|
-
*
|
|
57
|
-
* `application/*+json` parser to mark envelopes distinctly in listings.
|
|
60
|
+
* A shared strict UTF-8 decoder used to test whether a non-JSON payload is
|
|
61
|
+
* valid UTF-8 (so it can be stored legibly as text rather than base64).
|
|
62
|
+
* `fatal: true` makes `decode` throw on malformed input; the decoder is
|
|
63
|
+
* stateless across non-streaming calls, so one instance is reused.
|
|
58
64
|
*/
|
|
59
|
-
const
|
|
60
|
-
/**
|
|
61
|
-
* Marker property tagging an encrypted document whose decrypted content is a
|
|
62
|
-
* binary blob (rather than a JSON value), so `decode` can reconstruct a `Blob`.
|
|
63
|
-
* Namespaced to avoid colliding with caller JSON.
|
|
64
|
-
*/
|
|
65
|
-
const BLOB_MARKER = '@interop/was-client:edvBlob';
|
|
65
|
+
const UTF8_DECODER = new TextDecoder('utf-8', { fatal: true });
|
|
66
66
|
/**
|
|
67
67
|
* Heuristic for an EDV document id: multibase base58btc (leading `z`) of a
|
|
68
68
|
* 128-bit value. Used to reject human-readable ids on `put()`. Deliberately a
|
|
@@ -71,10 +71,6 @@ const BLOB_MARKER = '@interop/was-client:edvBlob';
|
|
|
71
71
|
* decode-and-length verification.
|
|
72
72
|
*/
|
|
73
73
|
const EDV_DOC_ID = /^z[1-9A-HJ-NP-Za-km-z]{21,}$/;
|
|
74
|
-
const ENCODER = new TextEncoder();
|
|
75
|
-
function isBlob(value) {
|
|
76
|
-
return typeof Blob !== 'undefined' && value instanceof Blob;
|
|
77
|
-
}
|
|
78
74
|
/**
|
|
79
75
|
* Encodes bytes to standard base64 using the platform `btoa` (present in modern
|
|
80
76
|
* Node and browsers), via a binary string.
|
|
@@ -105,11 +101,11 @@ function base64ToBytes(base64) {
|
|
|
105
101
|
}
|
|
106
102
|
/**
|
|
107
103
|
* A {@link ResourceCodec} that encrypts on write and decrypts on read using an
|
|
108
|
-
* `EdvClientCore`'s
|
|
104
|
+
* `EdvClientCore`'s public `documentCipher`. One instance is bound per encrypted
|
|
109
105
|
* collection handle.
|
|
110
106
|
*/
|
|
111
107
|
export class EdvCodec {
|
|
112
|
-
|
|
108
|
+
metadataMode = 'encrypted';
|
|
113
109
|
conditionalWrites = true;
|
|
114
110
|
_edv;
|
|
115
111
|
_keyAgreementKey;
|
|
@@ -138,20 +134,28 @@ export class EdvCodec {
|
|
|
138
134
|
'id, or carry the human-readable label inside the encrypted content.');
|
|
139
135
|
}
|
|
140
136
|
const docId = id ?? (await this._edv.generateId());
|
|
141
|
-
const content = await this.
|
|
137
|
+
const { content, meta } = await this._toDocument(data, contentType, docId);
|
|
142
138
|
// When the write path pre-read a current envelope, advance `sequence` from
|
|
143
|
-
// its prior value (`
|
|
139
|
+
// its prior value (`encrypt({ update: true })` increments it) and pin the
|
|
144
140
|
// write to the server's current ETag with `If-Match`. With no prior envelope
|
|
145
141
|
// this is a fresh insert (`sequence: 0`) guarded by `If-None-Match: *`
|
|
146
142
|
// (create-if-absent), so a concurrent first writer cannot be clobbered.
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
143
|
+
let priorDoc = null;
|
|
144
|
+
if (current) {
|
|
145
|
+
const read = await readJsonData(current);
|
|
146
|
+
this._assertEnvelope(read, 'update');
|
|
147
|
+
priorDoc = read;
|
|
148
|
+
}
|
|
149
|
+
const { documentCipher } = this._edv;
|
|
150
|
+
const recipients = documentCipher.createDefaultRecipients(this._keyAgreementKey);
|
|
151
|
+
const encrypted = await documentCipher.encrypt({
|
|
152
152
|
doc: {
|
|
153
153
|
id: docId,
|
|
154
154
|
content,
|
|
155
|
+
// `content` and `meta` are both sealed inside the JWE; `meta` carries the
|
|
156
|
+
// plaintext content type and the inline-encoding discriminator, taken
|
|
157
|
+
// fresh from this write (the new type/encoding wins on update).
|
|
158
|
+
meta,
|
|
155
159
|
...(priorDoc && { sequence: priorDoc.sequence })
|
|
156
160
|
},
|
|
157
161
|
recipients,
|
|
@@ -163,9 +167,17 @@ export class EdvCodec {
|
|
|
163
167
|
id: docId,
|
|
164
168
|
body: ENCODER.encode(JSON.stringify(encrypted)),
|
|
165
169
|
contentType: this._contentType,
|
|
170
|
+
// Surface the plaintext content type (the server-opaque envelope type stays
|
|
171
|
+
// `contentType`) so `add()` reports the real resource type.
|
|
172
|
+
resourceContentType: meta.contentType,
|
|
166
173
|
// Pin an update to the server's current ETag; guard a fresh insert with
|
|
167
|
-
// create-if-absent.
|
|
168
|
-
//
|
|
174
|
+
// create-if-absent. An update's `If-Match` carries a server-provided ETag,
|
|
175
|
+
// so it degrades to an advisory write against a backend without the
|
|
176
|
+
// conditional-writes feature (the ETag is absent). A fresh insert's
|
|
177
|
+
// `If-None-Match: *` needs no server-provided validator and so is emitted
|
|
178
|
+
// unconditionally by design -- it expresses the insert's intent
|
|
179
|
+
// (create-only-if-absent); a backend that does not honor it simply ignores
|
|
180
|
+
// it, leaving the write harmless rather than degraded.
|
|
169
181
|
...(priorDoc
|
|
170
182
|
? { ifMatch: current.headers.get('etag') ?? undefined }
|
|
171
183
|
: { ifNoneMatch: true })
|
|
@@ -175,74 +187,218 @@ export class EdvCodec {
|
|
|
175
187
|
* @inheritdoc
|
|
176
188
|
*/
|
|
177
189
|
async decode(response) {
|
|
178
|
-
const encryptedDoc =
|
|
179
|
-
|
|
190
|
+
const encryptedDoc = await readJsonData(response);
|
|
191
|
+
this._assertEnvelope(encryptedDoc, 'read');
|
|
192
|
+
const decrypted = await this._edv.documentCipher.decrypt({
|
|
180
193
|
encryptedDoc,
|
|
181
194
|
keyAgreementKey: this._keyAgreementKey
|
|
182
195
|
});
|
|
183
|
-
return this.
|
|
196
|
+
return this._fromDocument(decrypted.content, decrypted.meta);
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* @inheritdoc
|
|
200
|
+
*
|
|
201
|
+
* Encrypts the user-writable `custom` into an EDV Document envelope
|
|
202
|
+
* (`{ jwe, ... }`) with the same `documentCipher.encrypt` used for content --
|
|
203
|
+
* `custom` becomes the document `content`. The envelope's own `sequence` is
|
|
204
|
+
* inert (metadata concurrency is the server's plaintext `metaVersion`, not the
|
|
205
|
+
* envelope), so each write re-encrypts fresh with no `update`.
|
|
206
|
+
*/
|
|
207
|
+
async encodeMeta({ custom }) {
|
|
208
|
+
const { documentCipher } = this._edv;
|
|
209
|
+
const recipients = documentCipher.createDefaultRecipients(this._keyAgreementKey);
|
|
210
|
+
// The document needs an EDV id (the cipher asserts one on decrypt). It is
|
|
211
|
+
// opaque to the server -- carried inside the un-decryptable envelope -- and
|
|
212
|
+
// minted fresh each write, since the metadata envelope is never updated in
|
|
213
|
+
// place (concurrency is the server's plaintext `metaVersion`, Decision 3).
|
|
214
|
+
const id = (await this._edv.generateId());
|
|
215
|
+
const encrypted = await documentCipher.encrypt({
|
|
216
|
+
doc: { id, content: custom },
|
|
217
|
+
recipients,
|
|
218
|
+
keyResolver: this._edv.keyResolver,
|
|
219
|
+
hmac: undefined
|
|
220
|
+
});
|
|
221
|
+
return { custom: encrypted };
|
|
222
|
+
}
|
|
223
|
+
/**
|
|
224
|
+
* @inheritdoc
|
|
225
|
+
*
|
|
226
|
+
* Decrypts the stored `custom` envelope back to plaintext `{ name, tags }`. An
|
|
227
|
+
* absent `custom` (no metadata written yet, or cleared) decodes to `{}`; a
|
|
228
|
+
* present value must be an EDV envelope (else {@link EncryptionError}, the
|
|
229
|
+
* `_assertEnvelope` guard), so a foreign plaintext `custom` fails closed.
|
|
230
|
+
*/
|
|
231
|
+
async decodeMeta({ custom }) {
|
|
232
|
+
if (custom === undefined || custom === null) {
|
|
233
|
+
return {};
|
|
234
|
+
}
|
|
235
|
+
this._assertEnvelope(custom, 'read');
|
|
236
|
+
const decrypted = await this._edv.documentCipher.decrypt({
|
|
237
|
+
encryptedDoc: custom,
|
|
238
|
+
keyAgreementKey: this._keyAgreementKey
|
|
239
|
+
});
|
|
240
|
+
return (decrypted.content ?? {});
|
|
184
241
|
}
|
|
185
242
|
/**
|
|
186
|
-
*
|
|
187
|
-
*
|
|
188
|
-
*
|
|
189
|
-
* `
|
|
243
|
+
* Asserts that a document read from an encrypted collection is an EDV envelope
|
|
244
|
+
* (`{ jwe, ... }`) before it is handed to the cipher. A plaintext or foreign
|
|
245
|
+
* resource -- one written without this codec -- carries no `jwe`, which would
|
|
246
|
+
* otherwise make the EDV core throw a raw `TypeError`. Surfacing a typed
|
|
247
|
+
* `EncryptionError` keeps the fail-closed contract legible to callers.
|
|
190
248
|
*
|
|
191
|
-
* @param
|
|
192
|
-
* @param
|
|
193
|
-
*
|
|
249
|
+
* @param doc {unknown}
|
|
250
|
+
* @param context {string} the operation in progress (`read` / `update`),
|
|
251
|
+
* for the message
|
|
252
|
+
* @returns {asserts doc is IEncryptedDocument}
|
|
194
253
|
*/
|
|
195
|
-
|
|
254
|
+
_assertEnvelope(doc, context) {
|
|
255
|
+
const jwe = doc !== null && typeof doc === 'object'
|
|
256
|
+
? doc.jwe
|
|
257
|
+
: undefined;
|
|
258
|
+
if (jwe === null || typeof jwe !== 'object') {
|
|
259
|
+
throw new EncryptionError(`Cannot ${context} an encrypted resource: the stored document is not ` +
|
|
260
|
+
'an EDV envelope (it carries no `jwe` field). It was likely written ' +
|
|
261
|
+
'as plaintext, or by a writer that did not use this encrypted ' +
|
|
262
|
+
'collection.');
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Splits a caller value into a decrypted EDV document `{ content, meta }`,
|
|
267
|
+
* carrying the plaintext content type and inline-encoding discriminator in
|
|
268
|
+
* `meta`. Three cases:
|
|
269
|
+
*
|
|
270
|
+
* 1. JSON object/array to `content` verbatim, `meta = { contentType }` (no
|
|
271
|
+
* `encoding`); the shape of `content` is never inspected on read, so a
|
|
272
|
+
* caller object shaped like `{ text }` / `{ bytes }` round-trips as itself.
|
|
273
|
+
* 2. Text (`Blob`/`Uint8Array` of a text-family type that is valid UTF-8)
|
|
274
|
+
* to `content = { text }`, `meta = { contentType, encoding: 'utf-8' }`;
|
|
275
|
+
* stored legibly with no base64 inflation.
|
|
276
|
+
* 3. Binary (any other `Blob`/`Uint8Array`) to `content = { bytes: base64 }`,
|
|
277
|
+
* `meta = { contentType, encoding: 'base64' }`.
|
|
278
|
+
*
|
|
279
|
+
* A bare primitive is rejected (mirroring the plaintext `prepareBody`
|
|
280
|
+
* contract). The binary/text content type resolves as
|
|
281
|
+
* `contentType || blob.type || guessContentTypeFromId(id) || octet-stream`,
|
|
282
|
+
* mirroring `prepareBody`.
|
|
283
|
+
*
|
|
284
|
+
* @param data {ResourceData}
|
|
285
|
+
* @param [contentType] {string} caller-supplied content type
|
|
286
|
+
* @param [id] {string} resource id, for the extension guess
|
|
287
|
+
* @returns {Promise<{ content: Record<string, unknown>; meta:
|
|
288
|
+
* Record<string, unknown> }>}
|
|
289
|
+
*/
|
|
290
|
+
async _toDocument(data, contentType, id) {
|
|
291
|
+
let bytes;
|
|
292
|
+
let resolvedType;
|
|
196
293
|
if (isBlob(data)) {
|
|
197
|
-
|
|
198
|
-
|
|
294
|
+
bytes = new Uint8Array(await data.arrayBuffer());
|
|
295
|
+
resolvedType =
|
|
296
|
+
contentType ||
|
|
297
|
+
data.type ||
|
|
298
|
+
guessContentTypeFromId(id ?? '') ||
|
|
299
|
+
'application/octet-stream';
|
|
199
300
|
}
|
|
200
|
-
if (data instanceof Uint8Array) {
|
|
201
|
-
|
|
301
|
+
else if (data instanceof Uint8Array) {
|
|
302
|
+
bytes = data;
|
|
303
|
+
resolvedType =
|
|
304
|
+
contentType ||
|
|
305
|
+
guessContentTypeFromId(id ?? '') ||
|
|
306
|
+
'application/octet-stream';
|
|
307
|
+
}
|
|
308
|
+
if (bytes !== undefined && resolvedType !== undefined) {
|
|
309
|
+
if (bytes.length > this._maxBlobBytes) {
|
|
310
|
+
throw new ValidationError(`Encrypted binary write of ${bytes.length} bytes exceeds the ` +
|
|
311
|
+
`single-document limit of ${this._maxBlobBytes} bytes. Chunked ` +
|
|
312
|
+
"encrypted blobs need the server's chunked-streams affordance " +
|
|
313
|
+
'(not yet available).');
|
|
314
|
+
}
|
|
315
|
+
// Text-family AND valid UTF-8 to store as a legible string. The UTF-8 gate
|
|
316
|
+
// guarantees the bytes survive the string round-trip exactly; anything
|
|
317
|
+
// else falls through to base64, which is always byte-safe.
|
|
318
|
+
if (isTextContentType(resolvedType)) {
|
|
319
|
+
const text = decodeUtf8(bytes);
|
|
320
|
+
if (text !== null) {
|
|
321
|
+
return {
|
|
322
|
+
content: { text },
|
|
323
|
+
meta: { contentType: resolvedType, encoding: 'utf-8' }
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return {
|
|
328
|
+
content: { bytes: bytesToBase64(bytes) },
|
|
329
|
+
meta: { contentType: resolvedType, encoding: 'base64' }
|
|
330
|
+
};
|
|
202
331
|
}
|
|
203
332
|
if (data !== null && typeof data === 'object') {
|
|
204
|
-
|
|
333
|
+
// JSON object/array: content verbatim, no encoding (the read side treats an
|
|
334
|
+
// absent `meta.encoding` as JSON). EDV models `content` as an object
|
|
335
|
+
// record; a JSON array is also a valid encrypted value here, so widen it.
|
|
336
|
+
return {
|
|
337
|
+
content: data,
|
|
338
|
+
meta: { contentType: contentType ?? 'application/json' }
|
|
339
|
+
};
|
|
205
340
|
}
|
|
206
341
|
throw new ValidationError('Encrypted resource data must be a plain object/array (JSON) or a ' +
|
|
207
342
|
'Blob/Uint8Array (binary).');
|
|
208
343
|
}
|
|
209
344
|
/**
|
|
210
|
-
*
|
|
211
|
-
*
|
|
345
|
+
* Reconstructs a caller value from a decrypted EDV document, discriminating
|
|
346
|
+
* on `meta.encoding`:
|
|
212
347
|
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
`single-document limit of ${this._maxBlobBytes} bytes. Chunked ` +
|
|
221
|
-
"encrypted blobs need the server's chunked-streams affordance " +
|
|
222
|
-
'(not yet available).');
|
|
223
|
-
}
|
|
224
|
-
return { [BLOB_MARKER]: true, contentType, base64: bytesToBase64(bytes) };
|
|
225
|
-
}
|
|
226
|
-
/**
|
|
227
|
-
* Reconstructs a caller value from decrypted EDV document content: a `Blob`
|
|
228
|
-
* for a wrapped blob record, otherwise the JSON content verbatim.
|
|
348
|
+
* - `'utf-8'` to a `Blob` typed `meta.contentType` from `content.text`.
|
|
349
|
+
* - `'base64'` to a `Blob` typed `meta.contentType` from `content.bytes`.
|
|
350
|
+
* - absent (or `meta` absent) to `content` returned verbatim as JSON.
|
|
351
|
+
*
|
|
352
|
+
* A malformed inner shape (an encoding that does not match its container key's
|
|
353
|
+
* type) throws {@link EncryptionError} -- the decrypted-document analogue of
|
|
354
|
+
* `_assertEnvelope`'s outer guard.
|
|
229
355
|
*
|
|
230
356
|
* @param content {unknown}
|
|
357
|
+
* @param [meta] {Record<string, unknown>}
|
|
231
358
|
* @returns {Json | Blob}
|
|
232
359
|
*/
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const
|
|
238
|
-
|
|
239
|
-
|
|
360
|
+
_fromDocument(content, meta) {
|
|
361
|
+
const encoding = meta?.encoding;
|
|
362
|
+
const contentType = typeof meta?.contentType === 'string' ? meta.contentType : undefined;
|
|
363
|
+
if (encoding === 'utf-8') {
|
|
364
|
+
const text = content?.text;
|
|
365
|
+
if (typeof text !== 'string') {
|
|
366
|
+
throw new EncryptionError('Malformed encrypted text document: meta.encoding is "utf-8" but ' +
|
|
367
|
+
'content.text is not a string.');
|
|
368
|
+
}
|
|
369
|
+
return new Blob([ENCODER.encode(text)], { type: contentType });
|
|
370
|
+
}
|
|
371
|
+
if (encoding === 'base64') {
|
|
372
|
+
const base64 = content?.bytes;
|
|
373
|
+
if (typeof base64 !== 'string') {
|
|
374
|
+
throw new EncryptionError('Malformed encrypted binary document: meta.encoding is "base64" but ' +
|
|
375
|
+
'content.bytes is not a string.');
|
|
376
|
+
}
|
|
377
|
+
return new Blob([base64ToBytes(base64)], {
|
|
378
|
+
type: contentType
|
|
240
379
|
});
|
|
241
380
|
}
|
|
242
381
|
return content;
|
|
243
382
|
}
|
|
244
383
|
}
|
|
245
|
-
/**
|
|
384
|
+
/**
|
|
385
|
+
* Decodes bytes as strict UTF-8, returning `null` when they are not valid UTF-8
|
|
386
|
+
* (so the caller can fall back to base64). Uses the shared fatal decoder.
|
|
387
|
+
*
|
|
388
|
+
* @param bytes {Uint8Array}
|
|
389
|
+
* @returns {string | null}
|
|
390
|
+
*/
|
|
391
|
+
function decodeUtf8(bytes) {
|
|
392
|
+
try {
|
|
393
|
+
return UTF8_DECODER.decode(bytes);
|
|
394
|
+
}
|
|
395
|
+
catch {
|
|
396
|
+
return null;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
/**
|
|
400
|
+
* The EDV scheme tag this provider handles (matches the Collection marker).
|
|
401
|
+
*/
|
|
246
402
|
const EDV_SCHEME = 'edv';
|
|
247
403
|
/**
|
|
248
404
|
* Builds an {@link EncryptionProvider} for the `edv` scheme: a pure **keystore**
|
|
@@ -263,8 +419,8 @@ const EDV_SCHEME = 'edv';
|
|
|
263
419
|
* `{ keyAgreementKey, keyResolver }`, or `null` if this client holds no keys
|
|
264
420
|
* for it (fail-closed -- not a plaintext signal)
|
|
265
421
|
* @param [options.contentType] {string} stored envelope content type;
|
|
266
|
-
* defaults to `application/json`. Pass `
|
|
267
|
-
* (`application/
|
|
422
|
+
* defaults to `application/json`. Pass `JOSE_CONTENT_TYPE`
|
|
423
|
+
* (`application/jose+json`) against a server that registers an
|
|
268
424
|
* `application/*+json` parser.
|
|
269
425
|
* @param [options.maxBlobBytes] {number} single-document binary cap (default
|
|
270
426
|
* 1 MiB)
|
|
@@ -295,5 +451,4 @@ export function createEdvEncryption({ resolveKeys, contentType = DEFAULT_CONTENT
|
|
|
295
451
|
}
|
|
296
452
|
};
|
|
297
453
|
}
|
|
298
|
-
export { EDV_CONTENT_TYPE };
|
|
299
454
|
//# sourceMappingURL=EdvCodec.js.map
|
package/dist/edv/EdvCodec.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EdvCodec.js","sourceRoot":"","sources":["../../src/edv/EdvCodec.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"EdvCodec.js","sourceRoot":"","sources":["../../src/edv/EdvCodec.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,12 +19,12 @@
|
|
|
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 marker is `application/
|
|
22
|
+
* preferred marker is `application/jose+json` (exported as `JOSE_CONTENT_TYPE`),
|
|
23
23
|
* which distinguishes EDV envelopes from plaintext application JSON in
|
|
24
24
|
* listings and metadata -- but the server must register an `application/*+json`
|
|
25
25
|
* content-type parser to accept it (the reference was-teaching-server does; a
|
|
26
26
|
* server that does not will reject it with 415). Pass `contentType:
|
|
27
|
-
*
|
|
27
|
+
* JOSE_CONTENT_TYPE` to opt into it where the server supports it.
|
|
28
28
|
*
|
|
29
29
|
* Scope: documents only (`insert` / `update` / `get`). Blinded `find` / `count`
|
|
30
30
|
* / `updateIndex` and chunked streams (`storeChunk` / `getChunk`) require
|
|
@@ -36,13 +36,8 @@
|
|
|
36
36
|
import { Transport } from '@interop/edv-client';
|
|
37
37
|
import type { IEncryptedDocument } from '@interop/data-integrity-core';
|
|
38
38
|
import type { WasClient } from '../WasClient.js';
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
* envelope whose `jwe` property carries the ciphertext). Requires the server to
|
|
42
|
-
* register an `application/*+json` content-type parser; otherwise use the
|
|
43
|
-
* default `application/json` (see `WasTransport`'s `contentType` option).
|
|
44
|
-
*/
|
|
45
|
-
export declare const EDV_CONTENT_TYPE = "application/edv+json";
|
|
39
|
+
import { JOSE_CONTENT_TYPE } from './constants.js';
|
|
40
|
+
export { JOSE_CONTENT_TYPE };
|
|
46
41
|
/**
|
|
47
42
|
* The subset of `WasClient` this transport depends on: the signed-request
|
|
48
43
|
* escape hatch. Declared structurally so tests can supply a lightweight stub.
|
|
@@ -60,7 +55,7 @@ export declare class WasTransport extends Transport {
|
|
|
60
55
|
* @param options.collectionId {string} the vault Collection id
|
|
61
56
|
* @param [options.contentType] {string} content type for stored envelopes;
|
|
62
57
|
* defaults to `application/json` (accepted by an unmodified server). Pass
|
|
63
|
-
* `
|
|
58
|
+
* `JOSE_CONTENT_TYPE` against a server that registers an `application/*+json`
|
|
64
59
|
* parser.
|
|
65
60
|
*/
|
|
66
61
|
constructor({ was, spaceId, collectionId, contentType }: {
|
|
@@ -81,7 +76,7 @@ export declare class WasTransport extends Transport {
|
|
|
81
76
|
private _resourcePath;
|
|
82
77
|
/**
|
|
83
78
|
* Writes an encrypted document to its WAS resource path as
|
|
84
|
-
* `application/
|
|
79
|
+
* `application/jose+json` (the envelope serialized to bytes so the stored
|
|
85
80
|
* content type is exact).
|
|
86
81
|
*
|
|
87
82
|
* @param id {string}
|
|
@@ -174,5 +169,4 @@ export declare class WasTransport extends Transport {
|
|
|
174
169
|
*/
|
|
175
170
|
private _unsupported;
|
|
176
171
|
}
|
|
177
|
-
export {};
|
|
178
172
|
//# sourceMappingURL=WasTransport.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"WasTransport.d.ts","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE/C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAA;AACtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAIhD,OAAO,EAGL,iBAAiB,EAClB,MAAM,gBAAgB,CAAA;AAEvB,OAAO,EAAE,iBAAiB,EAAE,CAAA;AAE5B;;;GAGG;AACH,KAAK,YAAY,GAAG,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;AA8B9C,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;IAE5B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAc;IAEnC;;;;;;;;;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;IAQD;;;;;;;;OAQG;IACH,OAAO,CAAC,aAAa;IAIrB;;;;;;;;OAQG;YACW,IAAI;IAalB;;;;;;;;;;;;OAYG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAa1D;;;;;;;;;;OAUG;IACY,MAAM,CAAC,EACpB,SAAS,EACV,GAAE;QAAE,SAAS,CAAC,EAAE,kBAAkB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAoB1D;;;;;;;;;OASG;IACY,GAAG,CAAC,EACjB,EAAE,EACH,GAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAuBrD;;;;;;OAMG;YACW,OAAO;IAYrB;;;;;OAKG;IACY,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC;IAIrC;;;;OAIG;IACY,WAAW,IAAI,OAAO,CAAC,KAAK,CAAC;IAI5C;;;;OAIG;IACY,UAAU,IAAI,OAAO,CAAC,KAAK,CAAC;IAI3C;;;;OAIG;IACY,QAAQ,IAAI,OAAO,CAAC,KAAK,CAAC;IAIzC;;;;;;OAMG;IACH,OAAO,CAAC,YAAY;CAQrB"}
|
package/dist/edv/WasTransport.js
CHANGED
|
@@ -19,12 +19,12 @@
|
|
|
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 marker is `application/
|
|
22
|
+
* preferred marker is `application/jose+json` (exported as `JOSE_CONTENT_TYPE`),
|
|
23
23
|
* which distinguishes EDV envelopes from plaintext application JSON in
|
|
24
24
|
* listings and metadata -- but the server must register an `application/*+json`
|
|
25
25
|
* content-type parser to accept it (the reference was-teaching-server does; a
|
|
26
26
|
* server that does not will reject it with 415). Pass `contentType:
|
|
27
|
-
*
|
|
27
|
+
* JOSE_CONTENT_TYPE` to opt into it where the server supports it.
|
|
28
28
|
*
|
|
29
29
|
* Scope: documents only (`insert` / `update` / `get`). Blinded `find` / `count`
|
|
30
30
|
* / `updateIndex` and chunked streams (`storeChunk` / `getChunk`) require
|
|
@@ -37,23 +37,8 @@ import { Transport } from '@interop/edv-client';
|
|
|
37
37
|
import { httpStatus } from '../errors.js';
|
|
38
38
|
import { readJsonData } from '../internal/content.js';
|
|
39
39
|
import { resourcePath } from '../internal/paths.js';
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
* envelope whose `jwe` property carries the ciphertext). Requires the server to
|
|
43
|
-
* register an `application/*+json` content-type parser; otherwise use the
|
|
44
|
-
* default `application/json` (see `WasTransport`'s `contentType` option).
|
|
45
|
-
*/
|
|
46
|
-
export const EDV_CONTENT_TYPE = 'application/edv+json';
|
|
47
|
-
/**
|
|
48
|
-
* The content type used by default: plain JSON, which an unmodified WAS server
|
|
49
|
-
* accepts. The stored envelope is still self-identifying by its `jwe` field.
|
|
50
|
-
*/
|
|
51
|
-
const DEFAULT_CONTENT_TYPE = 'application/json';
|
|
52
|
-
/**
|
|
53
|
-
* A shared `TextEncoder` for serializing envelope bytes (stateless, so one
|
|
54
|
-
* instance is reused across every `_put`).
|
|
55
|
-
*/
|
|
56
|
-
const ENCODER = new TextEncoder();
|
|
40
|
+
import { DEFAULT_CONTENT_TYPE, ENCODER, JOSE_CONTENT_TYPE } from './constants.js';
|
|
41
|
+
export { JOSE_CONTENT_TYPE };
|
|
57
42
|
/**
|
|
58
43
|
* Builds an `Error` carrying the `name` that `EdvClientCore` (and the reference
|
|
59
44
|
* `HttpsTransport`) dispatch on -- `DuplicateError`, `InvalidStateError`,
|
|
@@ -85,7 +70,7 @@ export class WasTransport extends Transport {
|
|
|
85
70
|
* @param options.collectionId {string} the vault Collection id
|
|
86
71
|
* @param [options.contentType] {string} content type for stored envelopes;
|
|
87
72
|
* defaults to `application/json` (accepted by an unmodified server). Pass
|
|
88
|
-
* `
|
|
73
|
+
* `JOSE_CONTENT_TYPE` against a server that registers an `application/*+json`
|
|
89
74
|
* parser.
|
|
90
75
|
*/
|
|
91
76
|
constructor({ was, spaceId, collectionId, contentType = DEFAULT_CONTENT_TYPE }) {
|
|
@@ -109,7 +94,7 @@ export class WasTransport extends Transport {
|
|
|
109
94
|
}
|
|
110
95
|
/**
|
|
111
96
|
* Writes an encrypted document to its WAS resource path as
|
|
112
|
-
* `application/
|
|
97
|
+
* `application/jose+json` (the envelope serialized to bytes so the stored
|
|
113
98
|
* content type is exact).
|
|
114
99
|
*
|
|
115
100
|
* @param id {string}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAI/C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"WasTransport.js","sourceRoot":"","sources":["../../src/edv/WasTransport.ts"],"names":[],"mappings":"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"}
|