@interop/was-client 0.61.0 → 0.62.1

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.
Files changed (56) hide show
  1. package/README.md +58 -3
  2. package/dist/WasClient.d.ts +51 -6
  3. package/dist/WasClient.d.ts.map +1 -1
  4. package/dist/WasClient.js +84 -14
  5. package/dist/WasClient.js.map +1 -1
  6. package/dist/edv/EdvCodec.d.ts +4 -5
  7. package/dist/edv/EdvCodec.d.ts.map +1 -1
  8. package/dist/edv/EdvCodec.js +14 -11
  9. package/dist/edv/EdvCodec.js.map +1 -1
  10. package/dist/edv/epochRoster.d.ts +7 -32
  11. package/dist/edv/epochRoster.d.ts.map +1 -1
  12. package/dist/edv/epochRoster.js +10 -35
  13. package/dist/edv/epochRoster.js.map +1 -1
  14. package/dist/edv/recipients.d.ts +5 -0
  15. package/dist/edv/recipients.d.ts.map +1 -1
  16. package/dist/edv/recipients.js +15 -2
  17. package/dist/edv/recipients.js.map +1 -1
  18. package/dist/errors.d.ts +13 -0
  19. package/dist/errors.d.ts.map +1 -1
  20. package/dist/errors.js +13 -0
  21. package/dist/errors.js.map +1 -1
  22. package/dist/index.d.ts +2 -2
  23. package/dist/index.d.ts.map +1 -1
  24. package/dist/index.js +1 -1
  25. package/dist/index.js.map +1 -1
  26. package/dist/internal/cas.d.ts +10 -7
  27. package/dist/internal/cas.d.ts.map +1 -1
  28. package/dist/internal/cas.js +18 -7
  29. package/dist/internal/cas.js.map +1 -1
  30. package/dist/internal/describe.d.ts +6 -0
  31. package/dist/internal/describe.d.ts.map +1 -1
  32. package/dist/internal/describe.js +27 -1
  33. package/dist/internal/describe.js.map +1 -1
  34. package/dist/internal/pagination.d.ts +24 -1
  35. package/dist/internal/pagination.d.ts.map +1 -1
  36. package/dist/internal/pagination.js +77 -9
  37. package/dist/internal/pagination.js.map +1 -1
  38. package/dist/internal/paths.d.ts +0 -4
  39. package/dist/internal/paths.d.ts.map +1 -1
  40. package/dist/internal/paths.js +4 -9
  41. package/dist/internal/paths.js.map +1 -1
  42. package/dist/internal/request.d.ts +22 -6
  43. package/dist/internal/request.d.ts.map +1 -1
  44. package/dist/internal/request.js +31 -13
  45. package/dist/internal/request.js.map +1 -1
  46. package/dist/internal/service.d.ts +61 -0
  47. package/dist/internal/service.d.ts.map +1 -0
  48. package/dist/internal/service.js +259 -0
  49. package/dist/internal/service.js.map +1 -0
  50. package/dist/paths.d.ts +5 -1
  51. package/dist/paths.d.ts.map +1 -1
  52. package/dist/paths.js +5 -1
  53. package/dist/paths.js.map +1 -1
  54. package/dist/types.d.ts +28 -2
  55. package/dist/types.d.ts.map +1 -1
  56. package/package.json +2 -2
package/README.md CHANGED
@@ -13,6 +13,7 @@
13
13
  - [Usage](#usage)
14
14
  - [Creating a client (signer + zcapClient)](#creating-a-client-signer--zcapclient)
15
15
  - [Deriving a client from a secret or seed (`./identity`)](#deriving-a-client-from-a-secret-or-seed-identity)
16
+ - [Service discovery](#service-discovery)
16
17
  - [The handle model](#the-handle-model)
17
18
  - [Spaces](#spaces)
18
19
  - [Collections](#collections)
@@ -187,6 +188,50 @@ accepted. A server that verifies both it and the older `Ed25519Signature2020`
187
188
  accepts chains whose links mix the two, which is what a fleet upgrading at its
188
189
  own pace produces.
189
190
 
191
+ ### Service discovery
192
+
193
+ Before its first signed request, the client reads the server's service
194
+ description. It sends an unsigned `HEAD` to `serverUrl` and follows the
195
+ `Link: <...>; rel="service"` header on the response, whatever its status. Then
196
+ it reads the linked document with an unsigned `GET`. The spec fixes no path for
197
+ the document, so the client assumes none.
198
+
199
+ From the document the client selects the WAS specification version it speaks.
200
+ This client speaks only v0.5. It ignores `specs` keys other than
201
+ `https://w3id.org/pws` and entries without a `version`. If no entry names v0.5,
202
+ or the document is malformed, every signed request rejects with
203
+ `IncompatibleServerError` before anything is signed. A server whose responses
204
+ carry no `service` link predates v0.5 and is refused the same way. The client
205
+ does not fall back to the v0.4 layout.
206
+
207
+ Discovery runs once per client and is shared by every handle. A failure is not
208
+ memoized, so the next request retries. Unsigned public reads (`publicRead`,
209
+ `publicListCollection`, ...) take absolute URLs that may point at another
210
+ server, and do not wait on discovery.
211
+
212
+ `was.service()` returns what discovery found:
213
+
214
+ ```ts
215
+ const info = await was.service()
216
+ info.version // '0.5'
217
+ info.entry // the chosen `PwsVersionEntry`
218
+ info.description // the whole `ServiceDescription`
219
+ info.spacesUrl // the Spaces Repository URL, or undefined
220
+ info.features // e.g. ['listing', 'collection-management', ...]
221
+ info.hasFeature('quotas') // false when the token is absent
222
+
223
+ // Discover again, e.g. before relying on an affordance a host may have dropped.
224
+ await was.service({ refresh: true })
225
+ ```
226
+
227
+ `features` is an open token list. A token this client does not know is carried
228
+ along and otherwise ignored, and an absent token means unsupported. The client
229
+ gates no behavior on the document's `instance` member.
230
+
231
+ A caller that already holds the document (from a cache, say) can pass it as the
232
+ `serviceDescription` constructor option. The client then selects a version from
233
+ that copy without fetching, and `service({ refresh: true })` discovers afresh.
234
+
190
235
  ### The handle model
191
236
 
192
237
  The client exposes the WAS containment model
@@ -220,10 +265,13 @@ one item" footgun. The next sections cover each level in turn.
220
265
 
221
266
  A Space is the top-level container, created from the spaces repository. The
222
267
  server requires a `name`; `controller` defaults to the client's own DID, and the
223
- server generates the id unless you pass one.
268
+ server generates the id unless you pass one. `createSpace()` and `listSpaces()`
269
+ address the Spaces Repository URL the service description names (see
270
+ [Service discovery](#service-discovery)). Against a server whose description has
271
+ no `spaces` URL, they throw `NotSupportedError` without sending anything.
224
272
 
225
273
  ```ts
226
- const space = await was.createSpace({ name: 'Home' }) // POST /spaces/
274
+ const space = await was.createSpace({ name: 'Home' }) // POST {spacesUrl}
227
275
 
228
276
  // Lazy handle to an existing space by id -- no I/O until a verb runs.
229
277
  const same = was.space(space.id)
@@ -1134,7 +1182,8 @@ large Blobs to disk.)
1134
1182
  `was.request(...)` mirrors ezcap's generic `request()` for hand-built calls. As
1135
1183
  a deliberate escape hatch it returns the raw `HttpResponse` and throws raw
1136
1184
  ezcap/ky errors -- it does not apply the null-on-404 or typed-error
1137
- conveniences.
1185
+ conveniences. It still waits on service discovery, so against an incompatible
1186
+ server it rejects with `IncompatibleServerError`.
1138
1187
 
1139
1188
  ```ts
1140
1189
  const response = await was.request({ path: `/space/${spaceId}`, method: 'GET' })
@@ -1171,6 +1220,12 @@ instead, as `{ outcome: 'not-found' }`, rather than swallowing it.
1171
1220
  Spec endpoints a given server has not yet implemented surface as
1172
1221
  `NotImplementedError` (the server's 501).
1173
1222
 
1223
+ `IncompatibleServerError` comes from service discovery, not from a response
1224
+ status. Any signed method, read methods included, throws it when the server
1225
+ speaks no WAS version this client understands (see
1226
+ [Service discovery](#service-discovery)). It carries no `status`, so a read
1227
+ method does not mistake it for a 404.
1228
+
1174
1229
  ## Contribute
1175
1230
 
1176
1231
  PRs accepted. See [CONTRIBUTING.md](CONTRIBUTING.md) for editor setup (Prettier,
@@ -6,16 +6,18 @@
6
6
  * signer) and exposes the WAS containment model
7
7
  * (`SpacesRepository > Space > Collection > Resource`) through lazy
8
8
  * navigational handles. Also hosts the general delegation primitive
9
- * (`grant`), capability-rebuilding (`fromCapability`), and the signed
10
- * escape-hatch (`request`).
9
+ * (`grant`), capability-rebuilding (`fromCapability`), the signed
10
+ * escape-hatch (`request`), and service discovery (`service`), which every
11
+ * signed request waits on.
11
12
  */
12
13
  import type { ZcapClient } from '@interop/ezcap';
13
14
  import type { HttpResponse } from '@interop/http-client';
15
+ import type { ServiceDescription } from '@interop/storage-core';
14
16
  import type { EncryptionProvider } from './codec.js';
15
17
  import { Space } from './Space.js';
16
18
  import { Collection } from './Collection.js';
17
19
  import { Resource } from './Resource.js';
18
- import type { GrantOptions, HandleOptions, IDelegatedZcap, ISigner, IZcap, Json, RequestInput, CollectionResourcesList, ResourceSummary, SpaceListing } from './types.js';
20
+ import type { GrantOptions, HandleOptions, IDelegatedZcap, ISigner, IZcap, Json, RequestInput, CollectionResourcesList, ResourceSummary, ServiceInfo, SpaceListing } from './types.js';
19
21
  export declare class WasClient {
20
22
  #private;
21
23
  readonly serverUrl: string;
@@ -33,11 +35,18 @@ export declare class WasClient {
33
35
  * does not decide *which* collections are encrypted -- that is the
34
36
  * descriptor/override -- so a missing key for an encrypted collection fails
35
37
  * closed rather than silently downgrading to plaintext.
38
+ * @param [options.serviceDescription] {ServiceDescription} a service
39
+ * description the caller already holds (from a cache, say). The client
40
+ * selects its version from this copy instead of discovering the document
41
+ * from `serverUrl`, and still refuses it with `IncompatibleServerError` if
42
+ * it names no version this client speaks. `service({ refresh: true })`
43
+ * discards it and discovers afresh.
36
44
  */
37
- constructor({ serverUrl, zcapClient, encryption }: {
45
+ constructor({ serverUrl, zcapClient, encryption, serviceDescription }: {
38
46
  serverUrl: string;
39
47
  zcapClient: ZcapClient;
40
48
  encryption?: EncryptionProvider;
49
+ serviceDescription?: ServiceDescription;
41
50
  });
42
51
  /**
43
52
  * Convenience constructor that builds the ezcap `ZcapClient` internally from
@@ -52,12 +61,15 @@ export declare class WasClient {
52
61
  * @param options.serverUrl {string}
53
62
  * @param options.signer {ISigner}
54
63
  * @param [options.encryption] {EncryptionProvider} see the constructor
64
+ * @param [options.serviceDescription] {ServiceDescription} see the
65
+ * constructor
55
66
  * @returns {WasClient}
56
67
  */
57
- static fromSigner({ serverUrl, signer, encryption }: {
68
+ static fromSigner({ serverUrl, signer, encryption, serviceDescription }: {
58
69
  serverUrl: string;
59
70
  signer: ISigner;
60
71
  encryption?: EncryptionProvider;
72
+ serviceDescription?: ServiceDescription;
61
73
  }): WasClient;
62
74
  /**
63
75
  * The DID controlling the wrapped signer (`signer.id` without the key
@@ -66,6 +78,34 @@ export declare class WasClient {
66
78
  * @returns {string}
67
79
  */
68
80
  get controllerDid(): string;
81
+ /**
82
+ * Discovers the server's service description and the WAS version this
83
+ * client speaks with it. Follows the `rel="service"` link on the response to
84
+ * an unsigned `HEAD` of `serverUrl`, then reads the linked document with an
85
+ * unsigned `GET`. No capability is invoked. The result is memoized for the
86
+ * life of the client and shared by every handle; concurrent callers share
87
+ * one discovery, and a failure is not memoized, so the next call retries.
88
+ *
89
+ * Every signed request waits on this discovery, so a caller rarely needs to
90
+ * call it first. It is the way to read the server-wide affordances:
91
+ * `features` (an open token list, where an absent token means unsupported)
92
+ * and `spacesUrl` (absent when the server has no Spaces Repository).
93
+ * Unsigned public reads (`publicRead`, `publicListCollection`, ...) address
94
+ * an absolute URL that may be on another server, and do not wait on it.
95
+ *
96
+ * @param [options] {object}
97
+ * @param [options.refresh] {boolean} discard the memoized result (and any
98
+ * constructor-supplied `serviceDescription`) and discover again, for a
99
+ * caller about to rely on an affordance the server may have stopped
100
+ * advertising
101
+ * @returns {Promise<ServiceInfo>}
102
+ * @throws {IncompatibleServerError} when the server's responses carry no
103
+ * `service` link (it predates v0.5), the document is malformed, or it
104
+ * lists no version this client speaks
105
+ */
106
+ service(options?: {
107
+ refresh?: boolean;
108
+ }): Promise<ServiceInfo>;
69
109
  /**
70
110
  * Returns a lazy handle to a space by id. No I/O.
71
111
  *
@@ -78,13 +118,15 @@ export declare class WasClient {
78
118
  /**
79
119
  * Creates a space (server-generated id unless `id` is given). `name` is
80
120
  * optional (both in the spec and on the reference server); `controller` must
81
- * match the wrapped signer's DID (which is the default).
121
+ * match the wrapped signer's DID (which is the default). The request goes
122
+ * to the Spaces Repository URL the service description names.
82
123
  *
83
124
  * @param desc {object}
84
125
  * @param [desc.id] {string}
85
126
  * @param [desc.name] {string}
86
127
  * @param [desc.controller] {string}
87
128
  * @returns {Promise<Space>}
129
+ * @throws {NotSupportedError} when the server has no Spaces Repository
88
130
  */
89
131
  createSpace(desc?: {
90
132
  id?: string;
@@ -106,6 +148,7 @@ export declare class WasClient {
106
148
  * the walk has gathered the complete listing.
107
149
  *
108
150
  * @returns {Promise<SpaceListing>}
151
+ * @throws {NotSupportedError} when the server has no Spaces Repository
109
152
  */
110
153
  listSpaces(): Promise<SpaceListing>;
111
154
  /**
@@ -205,6 +248,8 @@ export declare class WasClient {
205
248
  * `path` against `serverUrl`, defaults `action` to `method`, and signs via the
206
249
  * wrapped client. Returns the raw `HttpResponse` and throws raw ky/ezcap
207
250
  * errors -- it does not apply the null-on-404 or typed-error conveniences.
251
+ * Like every signed request it waits on {@link service} first, and rejects
252
+ * with its `IncompatibleServerError` before signing anything.
208
253
  *
209
254
  * @param options {RequestInput}
210
255
  * @returns {Promise<HttpResponse>}
@@ -1 +1 @@
1
- {"version":3,"file":"WasClient.d.ts","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WasClient.d.ts","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
package/dist/WasClient.js CHANGED
@@ -1,10 +1,12 @@
1
- import { collectionItemsUrl, parseSpaceTarget, spacesRoot, toUrl } from './internal/paths.js';
1
+ import { collectionItemsUrl, parseSpaceTarget } from './internal/paths.js';
2
2
  import { send, rawRequest, unsignedRequest } from './internal/request.js';
3
3
  import { createdId, parseResource, readJsonData } from './internal/content.js';
4
4
  import { buildPageWalk, collectPages, collectWalk, signedPageWalk, walkItems, walkPagesOrEmpty } from './internal/pagination.js';
5
5
  import { delegateGrant } from './internal/grant.js';
6
6
  import { spaceIdOf, submitRevocation } from './internal/revoke.js';
7
- import { ValidationError, WasServerError } from './errors.js';
7
+ import { Memo } from './internal/memo.js';
8
+ import { discoverService, selectServiceVersion } from './internal/service.js';
9
+ import { NotSupportedError, ValidationError, WasServerError } from './errors.js';
8
10
  import { zcapClientForSigner } from './zcapClient.js';
9
11
  import { Space } from './Space.js';
10
12
  import { Collection } from './Collection.js';
@@ -25,11 +27,18 @@ export class WasClient {
25
27
  * does not decide *which* collections are encrypted -- that is the
26
28
  * descriptor/override -- so a missing key for an encrypted collection fails
27
29
  * closed rather than silently downgrading to plaintext.
30
+ * @param [options.serviceDescription] {ServiceDescription} a service
31
+ * description the caller already holds (from a cache, say). The client
32
+ * selects its version from this copy instead of discovering the document
33
+ * from `serverUrl`, and still refuses it with `IncompatibleServerError` if
34
+ * it names no version this client speaks. `service({ refresh: true })`
35
+ * discards it and discovers afresh.
28
36
  */
29
- constructor({ serverUrl, zcapClient, encryption }) {
37
+ constructor({ serverUrl, zcapClient, encryption, serviceDescription }) {
30
38
  this.serverUrl = serverUrl;
31
39
  this.zcapClient = zcapClient;
32
40
  this.encryption = encryption;
41
+ this.#serviceDescription = serviceDescription;
33
42
  }
34
43
  /**
35
44
  * Convenience constructor that builds the ezcap `ZcapClient` internally from
@@ -44,13 +53,16 @@ export class WasClient {
44
53
  * @param options.serverUrl {string}
45
54
  * @param options.signer {ISigner}
46
55
  * @param [options.encryption] {EncryptionProvider} see the constructor
56
+ * @param [options.serviceDescription] {ServiceDescription} see the
57
+ * constructor
47
58
  * @returns {WasClient}
48
59
  */
49
- static fromSigner({ serverUrl, signer, encryption }) {
60
+ static fromSigner({ serverUrl, signer, encryption, serviceDescription }) {
50
61
  return new WasClient({
51
62
  serverUrl,
52
63
  zcapClient: zcapClientForSigner({ signer }),
53
- encryption
64
+ encryption,
65
+ serviceDescription
54
66
  });
55
67
  }
56
68
  /**
@@ -66,6 +78,58 @@ export class WasClient {
66
78
  }
67
79
  return signer.id.split('#')[0];
68
80
  }
81
+ #serviceDescription;
82
+ #service = new Memo(async () => this.#serviceDescription === undefined
83
+ ? discoverService({ url: this.serverUrl })
84
+ : selectServiceVersion(this.#serviceDescription));
85
+ /**
86
+ * Discovers the server's service description and the WAS version this
87
+ * client speaks with it. Follows the `rel="service"` link on the response to
88
+ * an unsigned `HEAD` of `serverUrl`, then reads the linked document with an
89
+ * unsigned `GET`. No capability is invoked. The result is memoized for the
90
+ * life of the client and shared by every handle; concurrent callers share
91
+ * one discovery, and a failure is not memoized, so the next call retries.
92
+ *
93
+ * Every signed request waits on this discovery, so a caller rarely needs to
94
+ * call it first. It is the way to read the server-wide affordances:
95
+ * `features` (an open token list, where an absent token means unsupported)
96
+ * and `spacesUrl` (absent when the server has no Spaces Repository).
97
+ * Unsigned public reads (`publicRead`, `publicListCollection`, ...) address
98
+ * an absolute URL that may be on another server, and do not wait on it.
99
+ *
100
+ * @param [options] {object}
101
+ * @param [options.refresh] {boolean} discard the memoized result (and any
102
+ * constructor-supplied `serviceDescription`) and discover again, for a
103
+ * caller about to rely on an affordance the server may have stopped
104
+ * advertising
105
+ * @returns {Promise<ServiceInfo>}
106
+ * @throws {IncompatibleServerError} when the server's responses carry no
107
+ * `service` link (it predates v0.5), the document is malformed, or it
108
+ * lists no version this client speaks
109
+ */
110
+ async service(options = {}) {
111
+ if (options.refresh) {
112
+ this.#serviceDescription = undefined;
113
+ this.#service.reset();
114
+ }
115
+ return this.#service.get();
116
+ }
117
+ /**
118
+ * The Spaces Repository URL from the service description.
119
+ *
120
+ * @returns {Promise<string>}
121
+ * @throws {NotSupportedError} when the server does not implement the
122
+ * Spaces Repository
123
+ */
124
+ async #spacesUrl() {
125
+ const { spacesUrl, version } = await this.service();
126
+ if (spacesUrl === undefined) {
127
+ throw new NotSupportedError(`The server at "${this.serverUrl}" does not implement the Spaces ` +
128
+ `Repository: its WAS ${version} service description entry has no ` +
129
+ '`spaces` URL.');
130
+ }
131
+ return spacesUrl;
132
+ }
69
133
  #cachedContext;
70
134
  get #context() {
71
135
  // `serverUrl`, `zcapClient` (and thus `controllerDid`), and `encryption`
@@ -77,7 +141,8 @@ export class WasClient {
77
141
  serverUrl: this.serverUrl,
78
142
  zcapClient: this.zcapClient,
79
143
  controllerDid: this.controllerDid,
80
- encryption: this.encryption
144
+ encryption: this.encryption,
145
+ service: () => this.service()
81
146
  };
82
147
  }
83
148
  return this.#cachedContext;
@@ -100,13 +165,15 @@ export class WasClient {
100
165
  /**
101
166
  * Creates a space (server-generated id unless `id` is given). `name` is
102
167
  * optional (both in the spec and on the reference server); `controller` must
103
- * match the wrapped signer's DID (which is the default).
168
+ * match the wrapped signer's DID (which is the default). The request goes
169
+ * to the Spaces Repository URL the service description names.
104
170
  *
105
171
  * @param desc {object}
106
172
  * @param [desc.id] {string}
107
173
  * @param [desc.name] {string}
108
174
  * @param [desc.controller] {string}
109
175
  * @returns {Promise<Space>}
176
+ * @throws {NotSupportedError} when the server has no Spaces Repository
110
177
  */
111
178
  async createSpace(desc = {}) {
112
179
  const controller = desc.controller ?? this.controllerDid;
@@ -116,7 +183,7 @@ export class WasClient {
116
183
  ...(desc.name !== undefined && { name: desc.name })
117
184
  };
118
185
  const response = await send(this.#context, {
119
- path: spacesRoot(),
186
+ url: await this.#spacesUrl(),
120
187
  method: 'POST',
121
188
  json: body
122
189
  });
@@ -137,19 +204,20 @@ export class WasClient {
137
204
  * the walk has gathered the complete listing.
138
205
  *
139
206
  * @returns {Promise<SpaceListing>}
207
+ * @throws {NotSupportedError} when the server has no Spaces Repository
140
208
  */
141
209
  async listSpaces() {
210
+ const spacesUrl = await this.#spacesUrl();
142
211
  const walk = await signedPageWalk(this.#context, {
143
- firstUrl: toUrl({ serverUrl: this.serverUrl, path: spacesRoot() })
212
+ firstUrl: spacesUrl
144
213
  });
145
214
  // The first page always carries the listing body (an unauthorized caller
146
215
  // still gets an empty `items` list, not an error), so a `null` walk is a
147
- // server fault -- a 404 from a `serverUrl` whose base path does not reach
148
- // the repository, or a 2xx whose body did not parse as JSON. Report it as
149
- // one, rather than as a `TypeError` from destructuring `null`.
216
+ // server fault -- a 404 at the advertised repository URL, or a 2xx whose
217
+ // body did not parse as JSON. Report it as one, rather than as a
218
+ // `TypeError` from destructuring `null`.
150
219
  if (walk === null) {
151
- throw new WasServerError(`The space listing at "${this.serverUrl}" answered with no JSON ` +
152
- 'body. Check that `serverUrl` names the WAS repository root.');
220
+ throw new WasServerError(`The space listing at "${spacesUrl}" answered with no JSON body.`);
153
221
  }
154
222
  const listing = await collectPages(walk);
155
223
  // A paginating server omits `totalItems` on truncated pages; the walk has
@@ -341,6 +409,8 @@ export class WasClient {
341
409
  * `path` against `serverUrl`, defaults `action` to `method`, and signs via the
342
410
  * wrapped client. Returns the raw `HttpResponse` and throws raw ky/ezcap
343
411
  * errors -- it does not apply the null-on-404 or typed-error conveniences.
412
+ * Like every signed request it waits on {@link service} first, and rejects
413
+ * with its `IncompatibleServerError` before signing anything.
344
414
  *
345
415
  * @param options {RequestInput}
346
416
  * @returns {Promise<HttpResponse>}
@@ -1 +1 @@
1
- {"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
@@ -275,11 +275,10 @@ export declare function buildEdvCodec({ collectionId, label, transportFactory, e
275
275
  *
276
276
  * Applies the same fail-closed guards as `codecFor`: a future-scheme
277
277
  * descriptor and a descriptor without epochs are refused. The write epoch is
278
- * the descriptor's `currentEpoch`; a descriptor that omits it seals to the
279
- * last listed epoch (the roster is append-only, so that is the newest). A
280
- * `currentEpoch` the roster does not list violates the descriptor invariant
281
- * and is refused fail-closed -- silently re-routing it could seal new
282
- * plaintext to a rotated-out epoch whose removed recipients still hold keys.
278
+ * the descriptor's `currentEpoch`. A descriptor that omits it, or names an
279
+ * epoch the roster does not list, violates the descriptor invariant and is
280
+ * refused fail-closed -- guessing another entry could seal new plaintext to a
281
+ * rotated-out epoch whose removed recipients still hold keys.
283
282
  *
284
283
  * @param options {object}
285
284
  * @param options.collectionId {string} labels errors; and on a slot-bound
@@ -1 +1 @@
1
- {"version":3,"file":"EdvCodec.d.ts","sourceRoot":"","sources":["../../src/edv/EdvCodec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"EdvCodec.d.ts","sourceRoot":"","sources":["../../src/edv/EdvCodec.ts"],"names":[],"mappings":"AAwEA,OAAO,EAAE,aAAa,EAAe,MAAM,qBAAqB,CAAA;AAChE,OAAO,KAAK,EAGV,gBAAgB,EAChB,YAAY,EAEb,MAAM,8BAA8B,CAAA;AACrC,OAAO,KAAK,EAGV,aAAa,EACb,mBAAmB,EACnB,UAAU,EACV,kBAAkB,EAElB,YAAY,EACZ,aAAa,EACb,aAAa,EACb,YAAY,EACb,MAAM,aAAa,CAAA;AAepB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAMhD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAQ/C,OAAO,KAAK,EACV,oBAAoB,EACpB,IAAI,EACJ,YAAY,EACZ,sBAAsB,EACtB,2BAA2B,EAC5B,MAAM,aAAa,CAAA;AA8BpB;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,EAAE;IAC5C,OAAO,EAAE,mBAAmB,CAAA;IAC5B,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACzC,KAAK,YAAY,CAAA;AAElB;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,OAAO,EACP,YAAY,EACZ,WAAW,EACZ,EAAE;IACD,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,qBAAqB,CAUxB;AA4GD;;;;GAIG;AACH,qBAAa,QAAS,YAAW,aAAa;;IAC5C,QAAQ,CAAC,iBAAiB,QAAO;IAqFjC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;gBACS,EACV,GAAG,EACH,eAAe,EACf,QAAQ,EACR,UAAU,EACV,WAAW,EACX,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,OAAO,EACP,gBAAgB,EAChB,YAAY,EACZ,QAAQ,EACR,IAAI,EACL,EAAE;QACD,GAAG,EAAE,aAAa,CAAA;QAClB,eAAe,EAAE,gBAAgB,CAAA;QACjC,QAAQ,EAAE,gBAAgB,EAAE,CAAA;QAC5B,UAAU,EAAE,MAAM,CAAA;QAClB,WAAW,EAAE,MAAM,CAAA;QACnB,YAAY,EAAE,MAAM,CAAA;QACpB,SAAS,CAAC,EAAE,MAAM,CAAA;QAClB,YAAY,EAAE,QAAQ,GAAG,SAAS,CAAA;QAClC,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,gBAAgB,CAAC,EAAE,qBAAqB,CAAA;QACxC,YAAY,EAAE,MAAM,CAAA;QACpB,QAAQ,EAAE,MAAM,EAAE,CAAA;QAClB,IAAI,CAAC,EAAE,WAAW,GAAG,IAAI,CAAA;KAC1B;IA2BD;;;;OAIG;IACH,IAAI,WAAW,IAAI,WAAW,GAAG,IAAI,CAEpC;IAED;;OAEG;IACH,IAAI,QAAQ,IAAI,aAAa,GAAG,SAAS,CAExC;IAgED;;OAEG;IACG,MAAM,CAAC,EACX,EAAE,EACF,IAAI,EACJ,WAAW,EACX,OAAO,EACP,YAAY,EACb,EAAE;QACD,EAAE,CAAC,EAAE,MAAM,CAAA;QACX,IAAI,EAAE,YAAY,CAAA;QAClB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,YAAY,GAAG,IAAI,CAAA;QAC7B,YAAY,CAAC,EAAE,iBAAiB,CAAA;KACjC,GAAG,OAAO,CAAC,UAAU,CAAC;IAuZvB;;OAEG;IACG,MAAM,CACV,QAAQ,EAAE,YAAY,EACtB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAkdvB;;;;;;;;OAQG;IACG,UAAU,CAAC,EACf,MAAM,EACN,IAAI,EACL,EAAE;QACD,MAAM,EAAE,2BAA2B,CAAA;QACnC,IAAI,EAAE,aAAa,CAAA;KACpB,GAAG,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAwC9C;;;;;;;;;;;;;OAaG;IACG,UAAU,CACd,EACE,MAAM,EACP,EAAE;QACD,MAAM,CAAC,EAAE,OAAO,CAAA;KACjB,EACD,IAAI,EAAE,YAAY,GACjB,OAAO,CAAC,sBAAsB,CAAC;CAyOnC;AAqGD;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB,eAAe,EAAE,gBAAgB,CAAA;IACjC,WAAW,EAAE,YAAY,CAAA;IACzB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,WAAW,EACX,WAAkC,EAClC,YAAqC,EACrC,SAAS,EACT,YAAuB,EACxB,EAAE;IACD,WAAW,EAAE,CAAC,GAAG,EAAE;QACjB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;KACrB,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAA;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,YAAY,CAAC,EAAE,QAAQ,GAAG,SAAS,CAAA;CACpC,GAAG,kBAAkB,CA2CrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,wBAAsB,aAAa,CAAC,EAClC,YAAY,EACZ,KAA2B,EAC3B,gBAAgB,EAChB,UAAU,EACV,IAAI,EACJ,YAAY,EACZ,WAAkC,EAClC,YAAqC,EACrC,SAAS,EACV,EAAE;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gBAAgB,CAAC,EAAE,qBAAqB,CAAA;IACxC,UAAU,CAAC,EAAE,oBAAoB,CAAA;IACjC,IAAI,EAAE,OAAO,CAAA;IACb,YAAY,EAAE,QAAQ,GAAG,SAAS,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAwDpB;AAgFD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAsB,mBAAmB,CAAC,EACxC,YAAY,EACZ,YAAY,EACZ,UAAU,EACX,EAAE;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,SAAS,GAAG,QAAQ,CAAA;IAClC,UAAU,EAAE,oBAAoB,CAAA;CACjC,GAAG,OAAO,CAAC,QAAQ,CAAC,CA2BpB"}
@@ -79,7 +79,7 @@ import { WasTransport } from './WasTransport.js';
79
79
  import { isEncryptedEnvelope } from '../sync/envelope.js';
80
80
  import { epochWriteStandIn, resolveEpochKeys } from './epochKeys.js';
81
81
  import { didKeyResolver } from './epochCrypto.js';
82
- import { currentEpochOf } from './epochRoster.js';
82
+ import { currentEpochOf, hasKeyEpochs } from './epochRoster.js';
83
83
  import { resolveHmacKey } from './hmacKey.js';
84
84
  import { DECODER, isBlob, isTextContentType, readJsonData, resolvePayload } from '../internal/content.js';
85
85
  import { DEFAULT_CONTENT_TYPE, EDV_SCHEME_VERSION, envelopeBytes } from './constants.js';
@@ -1692,7 +1692,7 @@ export async function buildEdvCodec({ collectionId, label = `"${collectionId}"`,
1692
1692
  * @param options.label {string} names the collection in error messages
1693
1693
  * @param [options.encryption] {CollectionEncryption} the descriptor
1694
1694
  * @returns {CollectionEncryption} the descriptor, with `epochs` narrowed
1695
- * non-empty
1695
+ * non-empty and `currentEpoch` narrowed to a string
1696
1696
  */
1697
1697
  function guardEncryptionDescriptor({ label, encryption }) {
1698
1698
  const defect = descriptorDefect(encryption);
@@ -1705,8 +1705,9 @@ function guardEncryptionDescriptor({ label, encryption }) {
1705
1705
  * The one routability rule for an `edv` descriptor, shared by the throwing
1706
1706
  * guard and the provider's `canRoute`: names why this client cannot route the
1707
1707
  * descriptor as it stands (a scheme version newer than this client
1708
- * implements, or no key epochs), or `null` when it can. The reason reads as
1709
- * the predicate of a sentence whose subject is the collection.
1708
+ * implements, no key epochs, or no `currentEpoch`), or `null` when it can.
1709
+ * The reason reads as the predicate of a sentence whose subject is the
1710
+ * collection.
1710
1711
  *
1711
1712
  * @param [encryption] {CollectionEncryption}
1712
1713
  * @returns {string | null}
@@ -1726,6 +1727,10 @@ function descriptorDefect(encryption) {
1726
1727
  'a descriptor without one is refused rather than encrypted straight ' +
1727
1728
  'to a key-agreement key.');
1728
1729
  }
1730
+ if (!hasKeyEpochs(encryption)) {
1731
+ return ('declares key epochs but no currentEpoch, so the epoch to seal under ' +
1732
+ 'cannot be identified. Re-read the descriptor.');
1733
+ }
1729
1734
  return null;
1730
1735
  }
1731
1736
  /**
@@ -1741,11 +1746,10 @@ function descriptorDefect(encryption) {
1741
1746
  *
1742
1747
  * Applies the same fail-closed guards as `codecFor`: a future-scheme
1743
1748
  * descriptor and a descriptor without epochs are refused. The write epoch is
1744
- * the descriptor's `currentEpoch`; a descriptor that omits it seals to the
1745
- * last listed epoch (the roster is append-only, so that is the newest). A
1746
- * `currentEpoch` the roster does not list violates the descriptor invariant
1747
- * and is refused fail-closed -- silently re-routing it could seal new
1748
- * plaintext to a rotated-out epoch whose removed recipients still hold keys.
1749
+ * the descriptor's `currentEpoch`. A descriptor that omits it, or names an
1750
+ * epoch the roster does not list, violates the descriptor invariant and is
1751
+ * refused fail-closed -- guessing another entry could seal new plaintext to a
1752
+ * rotated-out epoch whose removed recipients still hold keys.
1749
1753
  *
1750
1754
  * @param options {object}
1751
1755
  * @param options.collectionId {string} labels errors; and on a slot-bound
@@ -1759,8 +1763,7 @@ export async function encryptOnlyEdvCodec({ collectionId, idDerivation, encrypti
1759
1763
  const label = `"${collectionId}"`;
1760
1764
  const descriptor = guardEncryptionDescriptor({ label, encryption });
1761
1765
  // `currentEpoch` MUST name a listed epoch (storage-core's descriptor
1762
- // invariant); with none declared, the last listed epoch is the newest,
1763
- // since the roster is append-only and the current epoch never moves back.
1766
+ // invariant); the list order is not trusted to put the newest epoch last.
1764
1767
  const writeEpoch = currentEpochOf({
1765
1768
  epochs: descriptor.epochs,
1766
1769
  currentEpoch: descriptor.currentEpoch,