@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.
- package/README.md +58 -3
- package/dist/WasClient.d.ts +51 -6
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +84 -14
- package/dist/WasClient.js.map +1 -1
- package/dist/edv/EdvCodec.d.ts +4 -5
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +14 -11
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/epochRoster.d.ts +7 -32
- package/dist/edv/epochRoster.d.ts.map +1 -1
- package/dist/edv/epochRoster.js +10 -35
- package/dist/edv/epochRoster.js.map +1 -1
- package/dist/edv/recipients.d.ts +5 -0
- package/dist/edv/recipients.d.ts.map +1 -1
- package/dist/edv/recipients.js +15 -2
- package/dist/edv/recipients.js.map +1 -1
- package/dist/errors.d.ts +13 -0
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +13 -0
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/cas.d.ts +10 -7
- package/dist/internal/cas.d.ts.map +1 -1
- package/dist/internal/cas.js +18 -7
- package/dist/internal/cas.js.map +1 -1
- package/dist/internal/describe.d.ts +6 -0
- package/dist/internal/describe.d.ts.map +1 -1
- package/dist/internal/describe.js +27 -1
- package/dist/internal/describe.js.map +1 -1
- package/dist/internal/pagination.d.ts +24 -1
- package/dist/internal/pagination.d.ts.map +1 -1
- package/dist/internal/pagination.js +77 -9
- package/dist/internal/pagination.js.map +1 -1
- package/dist/internal/paths.d.ts +0 -4
- package/dist/internal/paths.d.ts.map +1 -1
- package/dist/internal/paths.js +4 -9
- package/dist/internal/paths.js.map +1 -1
- package/dist/internal/request.d.ts +22 -6
- package/dist/internal/request.d.ts.map +1 -1
- package/dist/internal/request.js +31 -13
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/service.d.ts +61 -0
- package/dist/internal/service.d.ts.map +1 -0
- package/dist/internal/service.js +259 -0
- package/dist/internal/service.js.map +1 -0
- package/dist/paths.d.ts +5 -1
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +5 -1
- package/dist/paths.js.map +1 -1
- package/dist/types.d.ts +28 -2
- package/dist/types.d.ts.map +1 -1
- 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
|
|
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,
|
package/dist/WasClient.d.ts
CHANGED
|
@@ -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`),
|
|
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>}
|
package/dist/WasClient.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasClient.d.ts","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
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
|
|
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 {
|
|
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
|
-
|
|
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:
|
|
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
|
|
148
|
-
//
|
|
149
|
-
//
|
|
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 "${
|
|
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>}
|
package/dist/WasClient.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WasClient.js","sourceRoot":"","sources":["../src/WasClient.ts"],"names":[],"mappings":"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"}
|
package/dist/edv/EdvCodec.d.ts
CHANGED
|
@@ -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
|
|
279
|
-
*
|
|
280
|
-
*
|
|
281
|
-
*
|
|
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":"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"}
|
package/dist/edv/EdvCodec.js
CHANGED
|
@@ -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,
|
|
1709
|
-
* the predicate of a sentence whose subject is the
|
|
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
|
|
1745
|
-
*
|
|
1746
|
-
*
|
|
1747
|
-
*
|
|
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);
|
|
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,
|