@interop/was-conformance-suite 0.14.0 → 0.16.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 +1 -0
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +3 -6
- package/dist/helpers.js.map +1 -1
- package/dist/suites/authz-ordering-api.d.ts.map +1 -1
- package/dist/suites/authz-ordering-api.js +1 -26
- package/dist/suites/authz-ordering-api.js.map +1 -1
- package/dist/suites/blinded-index-api.d.ts.map +1 -1
- package/dist/suites/blinded-index-api.js +2 -4
- package/dist/suites/blinded-index-api.js.map +1 -1
- package/dist/suites/changes-query-api.js +1 -1
- package/dist/suites/changes-query-api.js.map +1 -1
- package/dist/suites/chunks-api.js +1 -1
- package/dist/suites/chunks-api.js.map +1 -1
- package/dist/suites/client-spaces.d.ts.map +1 -1
- package/dist/suites/client-spaces.js +19 -6
- package/dist/suites/client-spaces.js.map +1 -1
- package/dist/suites/collection-api.d.ts.map +1 -1
- package/dist/suites/collection-api.js +317 -126
- package/dist/suites/collection-api.js.map +1 -1
- package/dist/suites/conditional-requests-api.d.ts.map +1 -1
- package/dist/suites/conditional-requests-api.js +122 -30
- package/dist/suites/conditional-requests-api.js.map +1 -1
- package/dist/suites/delegation-cryptosuites-api.js +1 -1
- package/dist/suites/delegation-cryptosuites-api.js.map +1 -1
- package/dist/suites/denial-reasons-api.d.ts.map +1 -1
- package/dist/suites/denial-reasons-api.js +5 -2
- package/dist/suites/denial-reasons-api.js.map +1 -1
- package/dist/suites/digest-api.js +1 -1
- package/dist/suites/digest-api.js.map +1 -1
- package/dist/suites/encryption-descriptor-api.d.ts.map +1 -1
- package/dist/suites/encryption-descriptor-api.js +48 -51
- package/dist/suites/encryption-descriptor-api.js.map +1 -1
- package/dist/suites/governed-log-api.d.ts.map +1 -1
- package/dist/suites/governed-log-api.js +18 -17
- package/dist/suites/governed-log-api.js.map +1 -1
- package/dist/suites/index.d.ts +2 -1
- package/dist/suites/index.d.ts.map +1 -1
- package/dist/suites/index.js +3 -1
- package/dist/suites/index.js.map +1 -1
- package/dist/suites/invocation-target-api.js +1 -1
- package/dist/suites/invocation-target-api.js.map +1 -1
- package/dist/suites/plaintext-declaration-api.d.ts.map +1 -1
- package/dist/suites/plaintext-declaration-api.js +24 -15
- package/dist/suites/plaintext-declaration-api.js.map +1 -1
- package/dist/suites/policy-api.js +1 -1
- package/dist/suites/policy-api.js.map +1 -1
- package/dist/suites/reserved-methods-api.d.ts +9 -0
- package/dist/suites/reserved-methods-api.d.ts.map +1 -0
- package/dist/suites/reserved-methods-api.js +549 -0
- package/dist/suites/reserved-methods-api.js.map +1 -0
- package/dist/suites/resource-api.js +1 -1
- package/dist/suites/resource-api.js.map +1 -1
- package/dist/suites/spaces-api.d.ts.map +1 -1
- package/dist/suites/spaces-api.js +193 -63
- package/dist/suites/spaces-api.js.map +1 -1
- package/dist/suites/write-validation-api.d.ts.map +1 -1
- package/dist/suites/write-validation-api.js +16 -36
- package/dist/suites/write-validation-api.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,549 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* WAS conformance tests -- Methods at Reserved Endpoints (spec "Methods at
|
|
6
|
+
* Reserved Endpoints").
|
|
7
|
+
*
|
|
8
|
+
* A request to a reserved endpoint (see the spec's three Reserved Path
|
|
9
|
+
* Segment Registry tables) with a method the server does not implement there
|
|
10
|
+
* MUST be answered `405 Method Not Allowed`, with an `Allow` header naming
|
|
11
|
+
* the methods it does implement, an `about:blank` problem type, and the
|
|
12
|
+
* title "Method Not Allowed". An endpoint whose whole feature group is an
|
|
13
|
+
* OPTIONAL extension the server does not implement at all is instead
|
|
14
|
+
* governed by that group's own rule -- typically `unsupported-operation`
|
|
15
|
+
* (501) -- so most cases here accept a 501 in place of the 405. Every case
|
|
16
|
+
* is still required, since either answer is spec-conformant and any other
|
|
17
|
+
* answer is not. A method this specification never assigns an operation to
|
|
18
|
+
* anywhere (`PATCH`), and the container-URL `PUT` refusal, carry no 501
|
|
19
|
+
* escape.
|
|
20
|
+
*
|
|
21
|
+
* Every request is a signed root invocation by Alice: several reserved
|
|
22
|
+
* endpoints require authorization for unsafe methods before the refusal is
|
|
23
|
+
* ever reached (`requireAuthHeadersOrPublicRead` lets only safe methods
|
|
24
|
+
* through unauthenticated), so signing throughout keeps every case on the
|
|
25
|
+
* same footing. Raw `signCapabilityInvocation` + `fetch` is used instead of
|
|
26
|
+
* the high-level `ZcapClient.request()` so arbitrary methods (`PATCH`,
|
|
27
|
+
* `HEAD`) and bodyless success responses can be inspected directly, without
|
|
28
|
+
* the high-level client's success-body JSON parsing or its throw-on-4xx/5xx
|
|
29
|
+
* behavior getting in the way.
|
|
30
|
+
*/
|
|
31
|
+
import { signCapabilityInvocation } from '@interop/http-signature-zcap-invoke';
|
|
32
|
+
import assert from '../harness/assert.js';
|
|
33
|
+
/**
|
|
34
|
+
* Signs a raw capability invocation for an arbitrary method and sends it via
|
|
35
|
+
* `fetch`, returning the response untouched.
|
|
36
|
+
*
|
|
37
|
+
* @param options {object}
|
|
38
|
+
* @param options.url {string} the target URL
|
|
39
|
+
* @param options.method {string} the HTTP method to send
|
|
40
|
+
* @param options.invocationSigner {ISigner} the caller's signer
|
|
41
|
+
* @param [options.json] {object} an optional JSON body
|
|
42
|
+
* @returns {Promise<Response>}
|
|
43
|
+
*/
|
|
44
|
+
async function signedRequest({ url, method, invocationSigner, json }) {
|
|
45
|
+
const body = json === undefined
|
|
46
|
+
? undefined
|
|
47
|
+
: new TextEncoder().encode(JSON.stringify(json));
|
|
48
|
+
const signatureHeaders = await signCapabilityInvocation({
|
|
49
|
+
url,
|
|
50
|
+
method,
|
|
51
|
+
headers: {
|
|
52
|
+
date: new Date().toUTCString(),
|
|
53
|
+
...(body !== undefined && { 'content-type': 'application/json' })
|
|
54
|
+
},
|
|
55
|
+
...(body !== undefined && { body }),
|
|
56
|
+
invocationSigner,
|
|
57
|
+
capabilityAction: method
|
|
58
|
+
});
|
|
59
|
+
return fetch(url, {
|
|
60
|
+
method,
|
|
61
|
+
headers: signatureHeaders,
|
|
62
|
+
...(body !== undefined && { body: new Blob([body]) })
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Reads a `application/problem+json` body, or `undefined` for a bodyless
|
|
67
|
+
* response.
|
|
68
|
+
*
|
|
69
|
+
* @param response {Response}
|
|
70
|
+
* @returns {Promise<any>}
|
|
71
|
+
*/
|
|
72
|
+
async function readProblem(response) {
|
|
73
|
+
const text = await response.text();
|
|
74
|
+
return text ? JSON.parse(text) : undefined;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Splits an `Allow` header into its method tokens.
|
|
78
|
+
*
|
|
79
|
+
* @param allow {string | null}
|
|
80
|
+
* @returns {string[]}
|
|
81
|
+
*/
|
|
82
|
+
function allowedMethods(allow) {
|
|
83
|
+
return (allow ?? '')
|
|
84
|
+
.split(',')
|
|
85
|
+
.map(entry => entry.trim())
|
|
86
|
+
.filter(Boolean);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Sends a signed request for a method this specification does not define at
|
|
90
|
+
* `url`, and asserts the spec "Methods at Reserved Endpoints" refusal: `405`,
|
|
91
|
+
* an `Allow` header that does not name the refused method, and an
|
|
92
|
+
* `about:blank` problem body titled "Method Not Allowed". When `tolerate501`
|
|
93
|
+
* is set, a `501 unsupported-operation` is also accepted -- the endpoint's
|
|
94
|
+
* whole feature group may be unimplemented, in which case the group's own
|
|
95
|
+
* rule governs instead of this subsection.
|
|
96
|
+
*
|
|
97
|
+
* @param options {object}
|
|
98
|
+
* @param options.invocationSigner {ISigner}
|
|
99
|
+
* @param options.url {string}
|
|
100
|
+
* @param options.method {string}
|
|
101
|
+
* @param [options.tolerate501] {boolean}
|
|
102
|
+
* @returns {Promise<{ status: number; allow: string }>}
|
|
103
|
+
*/
|
|
104
|
+
async function assertMethodRefused({ invocationSigner, url, method, tolerate501 }) {
|
|
105
|
+
const needsBody = method === 'POST' || method === 'PUT' || method === 'PATCH';
|
|
106
|
+
const response = await signedRequest({
|
|
107
|
+
url,
|
|
108
|
+
method,
|
|
109
|
+
invocationSigner,
|
|
110
|
+
...(needsBody && { json: {} })
|
|
111
|
+
});
|
|
112
|
+
if (tolerate501 && response.status === 501) {
|
|
113
|
+
return { status: 501, allow: '' };
|
|
114
|
+
}
|
|
115
|
+
assert.equal(response.status, 405, `expected 405 for ${method} ${url}, got ${response.status}`);
|
|
116
|
+
const allow = response.headers.get('allow') ?? '';
|
|
117
|
+
assert.ok(!allowedMethods(allow).includes(method), `Allow header should not list ${method} for ${url} (got "${allow}")`);
|
|
118
|
+
assert.match(response.headers.get('content-type') ?? '', /application\/problem\+json/, `expected a problem+json body refusing ${method} ${url}`);
|
|
119
|
+
const problem = await readProblem(response);
|
|
120
|
+
assert.equal(problem?.type, 'about:blank', `expected an about:blank problem type refusing ${method} ${url}`);
|
|
121
|
+
assert.equal(problem?.title, 'Method Not Allowed', `expected the title "Method Not Allowed" refusing ${method} ${url}`);
|
|
122
|
+
return { status: 405, allow };
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Builds the URL for a reserved segment at the given container level.
|
|
126
|
+
*
|
|
127
|
+
* @param options {object}
|
|
128
|
+
* @param options.serverUrl {string}
|
|
129
|
+
* @param options.spaceId {string}
|
|
130
|
+
* @param options.collectionId {string}
|
|
131
|
+
* @param options.resourceId {string}
|
|
132
|
+
* @param options.level {'space' | 'collection' | 'resource'}
|
|
133
|
+
* @param options.segment {string} the reserved segment, e.g. `meta`
|
|
134
|
+
* @returns {string}
|
|
135
|
+
*/
|
|
136
|
+
function reservedEndpointUrl({ serverUrl, spaceId, collectionId, resourceId, level, segment }) {
|
|
137
|
+
let relativePath;
|
|
138
|
+
if (level === 'space') {
|
|
139
|
+
relativePath = `/space/${spaceId}/${segment}`;
|
|
140
|
+
}
|
|
141
|
+
else if (level === 'collection') {
|
|
142
|
+
relativePath = `/space/${spaceId}/${collectionId}/${segment}`;
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
relativePath = `/space/${spaceId}/${collectionId}/${resourceId}/${segment}`;
|
|
146
|
+
}
|
|
147
|
+
return new URL(relativePath, serverUrl).toString();
|
|
148
|
+
}
|
|
149
|
+
const RESERVED_ENDPOINT_CHECKS = [
|
|
150
|
+
// Space-level reserved endpoints (spec "Space-level reserved endpoints").
|
|
151
|
+
{
|
|
152
|
+
id: 'reserved-methods.space-meta-delete',
|
|
153
|
+
name: '[root] DELETE /space/:s/meta is refused (405)',
|
|
154
|
+
level: 'space',
|
|
155
|
+
segment: 'meta',
|
|
156
|
+
methods: ['DELETE'],
|
|
157
|
+
tolerate501: true,
|
|
158
|
+
specRefs: [
|
|
159
|
+
'https://wallet.storage/spec#space-metadata-data-model',
|
|
160
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
161
|
+
]
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
id: 'reserved-methods.space-policy-patch',
|
|
165
|
+
name: '[root] PATCH /space/:s/policy is refused (405)',
|
|
166
|
+
level: 'space',
|
|
167
|
+
segment: 'policy',
|
|
168
|
+
methods: ['PATCH'],
|
|
169
|
+
tolerate501: true,
|
|
170
|
+
specRefs: [
|
|
171
|
+
'https://wallet.storage/spec#space-level-reserved-endpoints',
|
|
172
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
173
|
+
]
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
id: 'reserved-methods.space-backends-patch',
|
|
177
|
+
name: '[root] PATCH /space/:s/backends is refused (405)',
|
|
178
|
+
level: 'space',
|
|
179
|
+
segment: 'backends',
|
|
180
|
+
methods: ['PATCH'],
|
|
181
|
+
tolerate501: true,
|
|
182
|
+
specRefs: [
|
|
183
|
+
'https://wallet.storage/spec#space-backends-available',
|
|
184
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
185
|
+
]
|
|
186
|
+
},
|
|
187
|
+
{
|
|
188
|
+
id: 'reserved-methods.space-collections-retired',
|
|
189
|
+
name: '[root] DELETE/PATCH /space/:s/collections are refused (405) -- the ' +
|
|
190
|
+
'retired segment defines no operation',
|
|
191
|
+
level: 'space',
|
|
192
|
+
segment: 'collections',
|
|
193
|
+
methods: ['DELETE', 'PATCH'],
|
|
194
|
+
tolerate501: false,
|
|
195
|
+
specRefs: [
|
|
196
|
+
'https://wallet.storage/spec#space-level-reserved-endpoints',
|
|
197
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
198
|
+
]
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
id: 'reserved-methods.space-export-get',
|
|
202
|
+
name: '[root] GET /space/:s/export is refused (405)',
|
|
203
|
+
level: 'space',
|
|
204
|
+
segment: 'export',
|
|
205
|
+
methods: ['GET'],
|
|
206
|
+
tolerate501: true,
|
|
207
|
+
specRefs: [
|
|
208
|
+
'https://wallet.storage/spec#space-level-reserved-endpoints',
|
|
209
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
210
|
+
]
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: 'reserved-methods.space-import-get',
|
|
214
|
+
name: '[root] GET /space/:s/import is refused (405)',
|
|
215
|
+
level: 'space',
|
|
216
|
+
segment: 'import',
|
|
217
|
+
methods: ['GET'],
|
|
218
|
+
tolerate501: true,
|
|
219
|
+
specRefs: [
|
|
220
|
+
'https://wallet.storage/spec#space-level-reserved-endpoints',
|
|
221
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
222
|
+
]
|
|
223
|
+
},
|
|
224
|
+
{
|
|
225
|
+
id: 'reserved-methods.space-linkset-delete',
|
|
226
|
+
name: '[root] DELETE /space/:s/linkset is refused (405)',
|
|
227
|
+
level: 'space',
|
|
228
|
+
segment: 'linkset',
|
|
229
|
+
methods: ['DELETE'],
|
|
230
|
+
tolerate501: true,
|
|
231
|
+
specRefs: [
|
|
232
|
+
'https://wallet.storage/spec#space-linkset',
|
|
233
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
234
|
+
]
|
|
235
|
+
},
|
|
236
|
+
{
|
|
237
|
+
id: 'reserved-methods.space-query-refused',
|
|
238
|
+
name: '[root] GET/PUT/DELETE/PATCH /space/:s/query are refused (405) -- no ' +
|
|
239
|
+
'cross-collection query operation is defined for them',
|
|
240
|
+
level: 'space',
|
|
241
|
+
segment: 'query',
|
|
242
|
+
methods: ['GET', 'PUT', 'DELETE', 'PATCH'],
|
|
243
|
+
tolerate501: false,
|
|
244
|
+
specRefs: [
|
|
245
|
+
'https://wallet.storage/spec#space-level-reserved-endpoints',
|
|
246
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
id: 'reserved-methods.space-quotas-put',
|
|
251
|
+
name: '[root] PUT /space/:s/quotas is refused (405)',
|
|
252
|
+
level: 'space',
|
|
253
|
+
segment: 'quotas',
|
|
254
|
+
methods: ['PUT'],
|
|
255
|
+
tolerate501: true,
|
|
256
|
+
specRefs: [
|
|
257
|
+
'https://wallet.storage/spec#quotas',
|
|
258
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
259
|
+
]
|
|
260
|
+
},
|
|
261
|
+
// Collection-level reserved endpoints (spec "Collection-level reserved
|
|
262
|
+
// endpoints"). The Collection need not exist -- the refusal reads no ids.
|
|
263
|
+
{
|
|
264
|
+
id: 'reserved-methods.collection-policy-patch',
|
|
265
|
+
name: '[root] PATCH /space/:s/:c/policy is refused (405)',
|
|
266
|
+
level: 'collection',
|
|
267
|
+
segment: 'policy',
|
|
268
|
+
methods: ['PATCH'],
|
|
269
|
+
tolerate501: true,
|
|
270
|
+
specRefs: [
|
|
271
|
+
'https://wallet.storage/spec#collection-level-reserved-endpoints',
|
|
272
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
273
|
+
]
|
|
274
|
+
},
|
|
275
|
+
{
|
|
276
|
+
id: 'reserved-methods.collection-backend-delete',
|
|
277
|
+
name: '[root] DELETE /space/:s/:c/backend is refused (405)',
|
|
278
|
+
level: 'collection',
|
|
279
|
+
segment: 'backend',
|
|
280
|
+
methods: ['DELETE'],
|
|
281
|
+
tolerate501: true,
|
|
282
|
+
specRefs: [
|
|
283
|
+
'https://wallet.storage/spec#collection-backend-selected',
|
|
284
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
285
|
+
]
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: 'reserved-methods.collection-linkset-delete',
|
|
289
|
+
name: '[root] DELETE /space/:s/:c/linkset is refused (405)',
|
|
290
|
+
level: 'collection',
|
|
291
|
+
segment: 'linkset',
|
|
292
|
+
methods: ['DELETE'],
|
|
293
|
+
tolerate501: true,
|
|
294
|
+
specRefs: [
|
|
295
|
+
'https://wallet.storage/spec#collection-linkset',
|
|
296
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
297
|
+
]
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
id: 'reserved-methods.collection-meta-delete',
|
|
301
|
+
name: '[root] DELETE /space/:s/:c/meta is refused (405)',
|
|
302
|
+
level: 'collection',
|
|
303
|
+
segment: 'meta',
|
|
304
|
+
methods: ['DELETE'],
|
|
305
|
+
tolerate501: true,
|
|
306
|
+
specRefs: [
|
|
307
|
+
'https://wallet.storage/spec#collection-metadata-data-model',
|
|
308
|
+
'https://wallet.storage/spec#collection-level-reserved-endpoints',
|
|
309
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
310
|
+
]
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
id: 'reserved-methods.collection-meta-log-delete',
|
|
314
|
+
name: '[root] DELETE /space/:s/:c/meta/log is refused (405)',
|
|
315
|
+
level: 'collection',
|
|
316
|
+
segment: 'meta/log',
|
|
317
|
+
methods: ['DELETE'],
|
|
318
|
+
tolerate501: true,
|
|
319
|
+
specRefs: [
|
|
320
|
+
'https://wallet.storage/spec#collection-governing-history-log',
|
|
321
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
id: 'reserved-methods.collection-query-get',
|
|
326
|
+
name: '[root] GET /space/:s/:c/query is refused (405)',
|
|
327
|
+
level: 'collection',
|
|
328
|
+
segment: 'query',
|
|
329
|
+
methods: ['GET'],
|
|
330
|
+
tolerate501: true,
|
|
331
|
+
specRefs: [
|
|
332
|
+
'https://wallet.storage/spec#query-profile-registry',
|
|
333
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
334
|
+
]
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
id: 'reserved-methods.collection-quota-put',
|
|
338
|
+
name: '[root] PUT /space/:s/:c/quota is refused (405)',
|
|
339
|
+
level: 'collection',
|
|
340
|
+
segment: 'quota',
|
|
341
|
+
methods: ['PUT'],
|
|
342
|
+
tolerate501: true,
|
|
343
|
+
specRefs: [
|
|
344
|
+
'https://wallet.storage/spec#quotas',
|
|
345
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
346
|
+
]
|
|
347
|
+
},
|
|
348
|
+
// Resource-level reserved endpoints (spec "Resource-level reserved
|
|
349
|
+
// endpoints"). Neither the Collection nor the Resource need exist.
|
|
350
|
+
{
|
|
351
|
+
id: 'reserved-methods.resource-meta-post',
|
|
352
|
+
name: '[root] POST /space/:s/:c/:r/meta is refused (405)',
|
|
353
|
+
level: 'resource',
|
|
354
|
+
segment: 'meta',
|
|
355
|
+
methods: ['POST'],
|
|
356
|
+
tolerate501: true,
|
|
357
|
+
specRefs: [
|
|
358
|
+
'https://wallet.storage/spec#resource-metadata-data-model',
|
|
359
|
+
'https://wallet.storage/spec#resource-level-reserved-endpoints',
|
|
360
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
361
|
+
]
|
|
362
|
+
},
|
|
363
|
+
{
|
|
364
|
+
id: 'reserved-methods.resource-chunks-delete',
|
|
365
|
+
name: '[root] DELETE /space/:s/:c/:r/chunks/ is refused (405)',
|
|
366
|
+
level: 'resource',
|
|
367
|
+
segment: 'chunks/',
|
|
368
|
+
methods: ['DELETE'],
|
|
369
|
+
tolerate501: true,
|
|
370
|
+
specRefs: [
|
|
371
|
+
'https://wallet.storage/spec#chunked-resources',
|
|
372
|
+
'https://wallet.storage/spec#resource-level-reserved-endpoints',
|
|
373
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
374
|
+
]
|
|
375
|
+
}
|
|
376
|
+
];
|
|
377
|
+
const reservedEndpointTests = RESERVED_ENDPOINT_CHECKS.map(check => ({
|
|
378
|
+
id: check.id,
|
|
379
|
+
name: check.name,
|
|
380
|
+
specRefs: check.specRefs,
|
|
381
|
+
run: async (ctx, state) => {
|
|
382
|
+
const { alice, collectionId, resourceId } = state;
|
|
383
|
+
const url = reservedEndpointUrl({
|
|
384
|
+
serverUrl: ctx.serverUrl,
|
|
385
|
+
spaceId: alice.space1.id,
|
|
386
|
+
collectionId,
|
|
387
|
+
resourceId,
|
|
388
|
+
level: check.level,
|
|
389
|
+
segment: check.segment
|
|
390
|
+
});
|
|
391
|
+
for (const method of check.methods) {
|
|
392
|
+
await assertMethodRefused({
|
|
393
|
+
invocationSigner: alice.rootClient.invocationSigner,
|
|
394
|
+
url,
|
|
395
|
+
method,
|
|
396
|
+
tolerate501: check.tolerate501
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}));
|
|
401
|
+
export const reservedMethodsApi = {
|
|
402
|
+
id: 'reserved-methods-api',
|
|
403
|
+
name: 'Methods at reserved endpoints (405)',
|
|
404
|
+
specRefs: [
|
|
405
|
+
'https://wallet.storage/spec#reserved-path-segment-registry',
|
|
406
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
407
|
+
],
|
|
408
|
+
setup: async (ctx) => {
|
|
409
|
+
const alice = { ...ctx.actors.alice };
|
|
410
|
+
alice.space1 = { id: ctx.generateId() };
|
|
411
|
+
await ctx.createSpace({
|
|
412
|
+
spaceDescription: {
|
|
413
|
+
id: alice.space1.id,
|
|
414
|
+
name: "Alice's Reserved-Methods Space",
|
|
415
|
+
controller: alice.did
|
|
416
|
+
},
|
|
417
|
+
rootClient: alice.rootClient
|
|
418
|
+
});
|
|
419
|
+
return {
|
|
420
|
+
alice,
|
|
421
|
+
// Neither Collection nor Resource need exist: the refusal reads no
|
|
422
|
+
// ids, so a plain literal id exercises the same code path as a real
|
|
423
|
+
// one without any provisioning cost.
|
|
424
|
+
collectionId: 'reserved-methods-collection',
|
|
425
|
+
resourceId: 'reserved-methods-resource'
|
|
426
|
+
};
|
|
427
|
+
},
|
|
428
|
+
teardown: async (ctx, state) => {
|
|
429
|
+
const { alice } = state;
|
|
430
|
+
try {
|
|
431
|
+
await alice.rootClient.request({
|
|
432
|
+
url: new URL(`/space/${alice.space1.id}/`, ctx.serverUrl).toString(),
|
|
433
|
+
method: 'DELETE'
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
catch {
|
|
437
|
+
/* best-effort cleanup */
|
|
438
|
+
}
|
|
439
|
+
},
|
|
440
|
+
tests: [
|
|
441
|
+
...reservedEndpointTests,
|
|
442
|
+
{
|
|
443
|
+
id: 'reserved-methods.space-container-put',
|
|
444
|
+
name: '[root] PUT /space/:s/ is refused (405), Allow excludes PUT',
|
|
445
|
+
specRefs: [
|
|
446
|
+
'https://wallet.storage/spec#space-metadata-data-model',
|
|
447
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
448
|
+
],
|
|
449
|
+
run: async (ctx, state) => {
|
|
450
|
+
const { alice } = state;
|
|
451
|
+
const url = new URL(`/space/${alice.space1.id}/`, ctx.serverUrl).toString();
|
|
452
|
+
await assertMethodRefused({
|
|
453
|
+
invocationSigner: alice.rootClient.invocationSigner,
|
|
454
|
+
url,
|
|
455
|
+
method: 'PUT'
|
|
456
|
+
});
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
{
|
|
460
|
+
id: 'reserved-methods.collection-container-put',
|
|
461
|
+
name: '[root] PUT /space/:s/:c/ is refused (405), Allow excludes PUT',
|
|
462
|
+
specRefs: [
|
|
463
|
+
'https://wallet.storage/spec#collection-metadata-data-model',
|
|
464
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints'
|
|
465
|
+
],
|
|
466
|
+
run: async (ctx, state) => {
|
|
467
|
+
const { alice, collectionId } = state;
|
|
468
|
+
const url = new URL(`/space/${alice.space1.id}/${collectionId}/`, ctx.serverUrl).toString();
|
|
469
|
+
await assertMethodRefused({
|
|
470
|
+
invocationSigner: alice.rootClient.invocationSigner,
|
|
471
|
+
url,
|
|
472
|
+
method: 'PUT'
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
{
|
|
477
|
+
id: 'reserved-methods.identical-for-absent-space',
|
|
478
|
+
name: '[root] the 405 refusal is identical whether the Space exists',
|
|
479
|
+
specRefs: [
|
|
480
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints',
|
|
481
|
+
'https://wallet.storage/spec#error-handling'
|
|
482
|
+
],
|
|
483
|
+
run: async (ctx, state) => {
|
|
484
|
+
const { alice } = state;
|
|
485
|
+
const answers = [];
|
|
486
|
+
for (const spaceId of [alice.space1.id, `absent-${ctx.generateId()}`]) {
|
|
487
|
+
const url = new URL(`/space/${spaceId}/`, ctx.serverUrl).toString();
|
|
488
|
+
answers.push(await assertMethodRefused({
|
|
489
|
+
invocationSigner: alice.rootClient.invocationSigner,
|
|
490
|
+
url,
|
|
491
|
+
method: 'PUT'
|
|
492
|
+
}));
|
|
493
|
+
}
|
|
494
|
+
assert.equal(answers[0].status, 405);
|
|
495
|
+
assert.deepStrictEqual(answers[1], answers[0], 'the refusal must read no ids: an absent Space gets the same answer');
|
|
496
|
+
}
|
|
497
|
+
},
|
|
498
|
+
{
|
|
499
|
+
id: 'reserved-methods.head-follows-get',
|
|
500
|
+
name: '[root] HEAD is not refused where GET is defined at a reserved ' +
|
|
501
|
+
'endpoint',
|
|
502
|
+
optional: true,
|
|
503
|
+
specRefs: [
|
|
504
|
+
'https://wallet.storage/spec#methods-at-reserved-endpoints',
|
|
505
|
+
'https://wallet.storage/spec#space-linkset'
|
|
506
|
+
],
|
|
507
|
+
run: async (ctx, state) => {
|
|
508
|
+
const { alice } = state;
|
|
509
|
+
const url = new URL(`/space/${alice.space1.id}/linkset`, ctx.serverUrl).toString();
|
|
510
|
+
const getResponse = await signedRequest({
|
|
511
|
+
url,
|
|
512
|
+
method: 'GET',
|
|
513
|
+
invocationSigner: alice.rootClient.invocationSigner
|
|
514
|
+
});
|
|
515
|
+
if (getResponse.status === 501) {
|
|
516
|
+
ctx.skip('Space Linkset (GET) not implemented (501)');
|
|
517
|
+
}
|
|
518
|
+
assert.notEqual(getResponse.status, 405, 'GET should not itself be refused');
|
|
519
|
+
const headResponse = await signedRequest({
|
|
520
|
+
url,
|
|
521
|
+
method: 'HEAD',
|
|
522
|
+
invocationSigner: alice.rootClient.invocationSigner
|
|
523
|
+
});
|
|
524
|
+
assert.notEqual(headResponse.status, 405, 'HEAD should follow GET rather than being refused');
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
id: 'reserved-methods.options-preflight-not-refused',
|
|
529
|
+
name: '[root] an OPTIONS CORS preflight at a reserved endpoint is not ' +
|
|
530
|
+
'refused',
|
|
531
|
+
optional: true,
|
|
532
|
+
specRefs: ['https://wallet.storage/spec#methods-at-reserved-endpoints'],
|
|
533
|
+
run: async (ctx, state) => {
|
|
534
|
+
const { alice } = state;
|
|
535
|
+
const url = new URL(`/space/${alice.space1.id}/linkset`, ctx.serverUrl).toString();
|
|
536
|
+
const response = await fetch(url, {
|
|
537
|
+
method: 'OPTIONS',
|
|
538
|
+
headers: {
|
|
539
|
+
origin: 'https://app.example',
|
|
540
|
+
'access-control-request-method': 'DELETE'
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
assert.notEqual(response.status, 405, 'an OPTIONS preflight must not be caught by the reserved-methods ' +
|
|
544
|
+
'refusal');
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
]
|
|
548
|
+
};
|
|
549
|
+
//# sourceMappingURL=reserved-methods-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reserved-methods-api.js","sourceRoot":"","sources":["../../src/suites/reserved-methods-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAA;AAE9E,OAAO,MAAM,MAAM,sBAAsB,CAAA;AASzC;;;;;;;;;;GAUG;AACH,KAAK,UAAU,aAAa,CAAC,EAC3B,GAAG,EACH,MAAM,EACN,gBAAgB,EAChB,IAAI,EAML;IACC,MAAM,IAAI,GACR,IAAI,KAAK,SAAS;QAChB,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;IACpD,MAAM,gBAAgB,GAAG,MAAM,wBAAwB,CAAC;QACtD,GAAG;QACH,MAAM;QACN,OAAO,EAAE;YACP,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YAC9B,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,cAAc,EAAE,kBAAkB,EAAE,CAAC;SAClE;QACD,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC;QACnC,gBAAgB;QAChB,gBAAgB,EAAE,MAAM;KACzB,CAAC,CAAA;IACF,OAAO,KAAK,CAAC,GAAG,EAAE;QAChB,MAAM;QACN,OAAO,EAAE,gBAA0C;QACnD,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;KACtD,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,WAAW,CAAC,QAAkB;IAC3C,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAA;IAClC,OAAO,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5C,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,KAAoB;IAC1C,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC;SACjB,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,OAAO,CAAC,CAAA;AACpB,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,KAAK,UAAU,mBAAmB,CAAC,EACjC,gBAAgB,EAChB,GAAG,EACH,MAAM,EACN,WAAW,EAMZ;IACC,MAAM,SAAS,GAAG,MAAM,KAAK,MAAM,IAAI,MAAM,KAAK,KAAK,IAAI,MAAM,KAAK,OAAO,CAAA;IAC7E,MAAM,QAAQ,GAAG,MAAM,aAAa,CAAC;QACnC,GAAG;QACH,MAAM;QACN,gBAAgB;QAChB,GAAG,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC;KAC/B,CAAC,CAAA;IACF,IAAI,WAAW,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;QAC3C,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,CAAA;IACnC,CAAC;IACD,MAAM,CAAC,KAAK,CACV,QAAQ,CAAC,MAAM,EACf,GAAG,EACH,oBAAoB,MAAM,IAAI,GAAG,SAAS,QAAQ,CAAC,MAAM,EAAE,CAC5D,CAAA;IACD,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAA;IACjD,MAAM,CAAC,EAAE,CACP,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EACvC,gCAAgC,MAAM,QAAQ,GAAG,UAAU,KAAK,IAAI,CACrE,CAAA;IACD,MAAM,CAAC,KAAK,CACV,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE,EAC1C,4BAA4B,EAC5B,yCAAyC,MAAM,IAAI,GAAG,EAAE,CACzD,CAAA;IACD,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAA;IAC3C,MAAM,CAAC,KAAK,CACV,OAAO,EAAE,IAAI,EACb,aAAa,EACb,iDAAiD,MAAM,IAAI,GAAG,EAAE,CACjE,CAAA;IACD,MAAM,CAAC,KAAK,CACV,OAAO,EAAE,KAAK,EACd,oBAAoB,EACpB,oDAAoD,MAAM,IAAI,GAAG,EAAE,CACpE,CAAA;IACD,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,KAAK,EAAE,CAAA;AAC/B,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAS,mBAAmB,CAAC,EAC3B,SAAS,EACT,OAAO,EACP,YAAY,EACZ,UAAU,EACV,KAAK,EACL,OAAO,EAQR;IACC,IAAI,YAAoB,CAAA;IACxB,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,YAAY,GAAG,UAAU,OAAO,IAAI,OAAO,EAAE,CAAA;IAC/C,CAAC;SAAM,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;QAClC,YAAY,GAAG,UAAU,OAAO,IAAI,YAAY,IAAI,OAAO,EAAE,CAAA;IAC/D,CAAC;SAAM,CAAC;QACN,YAAY,GAAG,UAAU,OAAO,IAAI,YAAY,IAAI,UAAU,IAAI,OAAO,EAAE,CAAA;IAC7E,CAAC;IACD,OAAO,IAAI,GAAG,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAA;AACpD,CAAC;AAmBD,MAAM,wBAAwB,GAA4B;IACxD,0EAA0E;IAC1E;QACE,EAAE,EAAE,oCAAoC;QACxC,IAAI,EAAE,+CAA+C;QACrD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,uDAAuD;YACvD,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,qCAAqC;QACzC,IAAI,EAAE,gDAAgD;QACtD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,CAAC,OAAO,CAAC;QAClB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,4DAA4D;YAC5D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,uCAAuC;QAC3C,IAAI,EAAE,kDAAkD;QACxD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,UAAU;QACnB,OAAO,EAAE,CAAC,OAAO,CAAC;QAClB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,sDAAsD;YACtD,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,4CAA4C;QAChD,IAAI,EACF,qEAAqE;YACrE,sCAAsC;QACxC,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,aAAa;QACtB,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,CAAC;QAC5B,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE;YACR,4DAA4D;YAC5D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,mCAAmC;QACvC,IAAI,EAAE,8CAA8C;QACpD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,4DAA4D;YAC5D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,mCAAmC;QACvC,IAAI,EAAE,8CAA8C;QACpD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,4DAA4D;YAC5D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,uCAAuC;QAC3C,IAAI,EAAE,kDAAkD;QACxD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,2CAA2C;YAC3C,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,sCAAsC;QAC1C,IAAI,EACF,sEAAsE;YACtE,sDAAsD;QACxD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC;QAC1C,WAAW,EAAE,KAAK;QAClB,QAAQ,EAAE;YACR,4DAA4D;YAC5D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,mCAAmC;QACvC,IAAI,EAAE,8CAA8C;QACpD,KAAK,EAAE,OAAO;QACd,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,oCAAoC;YACpC,2DAA2D;SAC5D;KACF;IACD,uEAAuE;IACvE,0EAA0E;IAC1E;QACE,EAAE,EAAE,0CAA0C;QAC9C,IAAI,EAAE,mDAAmD;QACzD,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,QAAQ;QACjB,OAAO,EAAE,CAAC,OAAO,CAAC;QAClB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,iEAAiE;YACjE,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,4CAA4C;QAChD,IAAI,EAAE,qDAAqD;QAC3D,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,yDAAyD;YACzD,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,4CAA4C;QAChD,IAAI,EAAE,qDAAqD;QAC3D,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,gDAAgD;YAChD,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,yCAAyC;QAC7C,IAAI,EAAE,kDAAkD;QACxD,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,4DAA4D;YAC5D,iEAAiE;YACjE,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,6CAA6C;QACjD,IAAI,EAAE,sDAAsD;QAC5D,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,UAAU;QACnB,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,8DAA8D;YAC9D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,uCAAuC;QAC3C,IAAI,EAAE,gDAAgD;QACtD,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,oDAAoD;YACpD,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,uCAAuC;QAC3C,IAAI,EAAE,gDAAgD;QACtD,KAAK,EAAE,YAAY;QACnB,OAAO,EAAE,OAAO;QAChB,OAAO,EAAE,CAAC,KAAK,CAAC;QAChB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,oCAAoC;YACpC,2DAA2D;SAC5D;KACF;IACD,mEAAmE;IACnE,mEAAmE;IACnE;QACE,EAAE,EAAE,qCAAqC;QACzC,IAAI,EAAE,mDAAmD;QACzD,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,MAAM;QACf,OAAO,EAAE,CAAC,MAAM,CAAC;QACjB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,0DAA0D;YAC1D,+DAA+D;YAC/D,2DAA2D;SAC5D;KACF;IACD;QACE,EAAE,EAAE,yCAAyC;QAC7C,IAAI,EAAE,wDAAwD;QAC9D,KAAK,EAAE,UAAU;QACjB,OAAO,EAAE,SAAS;QAClB,OAAO,EAAE,CAAC,QAAQ,CAAC;QACnB,WAAW,EAAE,IAAI;QACjB,QAAQ,EAAE;YACR,+CAA+C;YAC/C,+DAA+D;YAC/D,2DAA2D;SAC5D;KACF;CACF,CAAA;AAED,MAAM,qBAAqB,GACzB,wBAAwB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrC,EAAE,EAAE,KAAK,CAAC,EAAE;IACZ,IAAI,EAAE,KAAK,CAAC,IAAI;IAChB,QAAQ,EAAE,KAAK,CAAC,QAAQ;IACxB,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QACxB,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,UAAU,EAAE,GAAG,KAAK,CAAA;QACjD,MAAM,GAAG,GAAG,mBAAmB,CAAC;YAC9B,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,OAAO,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;YACxB,YAAY;YACZ,UAAU;YACV,KAAK,EAAE,KAAK,CAAC,KAAK;YAClB,OAAO,EAAE,KAAK,CAAC,OAAO;SACvB,CAAC,CAAA;QACF,KAAK,MAAM,MAAM,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACnC,MAAM,mBAAmB,CAAC;gBACxB,gBAAgB,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB;gBACnD,GAAG;gBACH,MAAM;gBACN,WAAW,EAAE,KAAK,CAAC,WAAW;aAC/B,CAAC,CAAA;QACJ,CAAC;IACH,CAAC;CACF,CAAC,CAAC,CAAA;AAEL,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,EAAE,EAAE,sBAAsB;IAC1B,IAAI,EAAE,qCAAqC;IAC3C,QAAQ,EAAE;QACR,4DAA4D;QAC5D,2DAA2D;KAC5D;IAED,KAAK,EAAE,KAAK,EAAC,GAAG,EAAC,EAAE;QACjB,MAAM,KAAK,GAAQ,EAAE,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,EAAE,CAAA;QAC1C,KAAK,CAAC,MAAM,GAAG,EAAE,EAAE,EAAE,GAAG,CAAC,UAAU,EAAE,EAAE,CAAA;QACvC,MAAM,GAAG,CAAC,WAAW,CAAC;YACpB,gBAAgB,EAAE;gBAChB,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,EAAE;gBACnB,IAAI,EAAE,gCAAgC;gBACtC,UAAU,EAAE,KAAK,CAAC,GAAG;aACtB;YACD,UAAU,EAAE,KAAK,CAAC,UAAU;SAC7B,CAAC,CAAA;QACF,OAAO;YACL,KAAK;YACL,mEAAmE;YACnE,oEAAoE;YACpE,qCAAqC;YACrC,YAAY,EAAE,6BAA6B;YAC3C,UAAU,EAAE,2BAA2B;SACxC,CAAA;IACH,CAAC;IAED,QAAQ,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;QAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;QACvB,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC;gBAC7B,GAAG,EAAE,IAAI,GAAG,CAAC,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE;gBACpE,MAAM,EAAE,QAAQ;aACjB,CAAC,CAAA;QACJ,CAAC;QAAC,MAAM,CAAC;YACP,yBAAyB;QAC3B,CAAC;IACH,CAAC;IAED,KAAK,EAAE;QACL,GAAG,qBAAqB;QACxB;YACE,EAAE,EAAE,sCAAsC;YAC1C,IAAI,EAAE,4DAA4D;YAClE,QAAQ,EAAE;gBACR,uDAAuD;gBACvD,2DAA2D;aAC5D;YACD,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACxB,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;gBACvB,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,GAAG,EAC5B,GAAG,CAAC,SAAS,CACd,CAAC,QAAQ,EAAE,CAAA;gBACZ,MAAM,mBAAmB,CAAC;oBACxB,gBAAgB,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB;oBACnD,GAAG;oBACH,MAAM,EAAE,KAAK;iBACd,CAAC,CAAA;YACJ,CAAC;SACF;QACD;YACE,EAAE,EAAE,2CAA2C;YAC/C,IAAI,EAAE,+DAA+D;YACrE,QAAQ,EAAE;gBACR,4DAA4D;gBAC5D,2DAA2D;aAC5D;YACD,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACxB,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,GAAG,KAAK,CAAA;gBACrC,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,IAAI,YAAY,GAAG,EAC5C,GAAG,CAAC,SAAS,CACd,CAAC,QAAQ,EAAE,CAAA;gBACZ,MAAM,mBAAmB,CAAC;oBACxB,gBAAgB,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB;oBACnD,GAAG;oBACH,MAAM,EAAE,KAAK;iBACd,CAAC,CAAA;YACJ,CAAC;SACF;QACD;YACE,EAAE,EAAE,6CAA6C;YACjD,IAAI,EAAE,8DAA8D;YACpE,QAAQ,EAAE;gBACR,2DAA2D;gBAC3D,4CAA4C;aAC7C;YACD,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACxB,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;gBACvB,MAAM,OAAO,GAA6C,EAAE,CAAA;gBAC5D,KAAK,MAAM,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,UAAU,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC;oBACtE,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,UAAU,OAAO,GAAG,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAA;oBACnE,OAAO,CAAC,IAAI,CACV,MAAM,mBAAmB,CAAC;wBACxB,gBAAgB,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB;wBACnD,GAAG;wBACH,MAAM,EAAE,KAAK;qBACd,CAAC,CACH,CAAA;gBACH,CAAC;gBACD,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAE,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;gBACrC,MAAM,CAAC,eAAe,CACpB,OAAO,CAAC,CAAC,CAAC,EACV,OAAO,CAAC,CAAC,CAAC,EACV,oEAAoE,CACrE,CAAA;YACH,CAAC;SACF;QACD;YACE,EAAE,EAAE,mCAAmC;YACvC,IAAI,EACF,gEAAgE;gBAChE,UAAU;YACZ,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE;gBACR,2DAA2D;gBAC3D,2CAA2C;aAC5C;YACD,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACxB,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;gBACvB,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EACnC,GAAG,CAAC,SAAS,CACd,CAAC,QAAQ,EAAE,CAAA;gBACZ,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC;oBACtC,GAAG;oBACH,MAAM,EAAE,KAAK;oBACb,gBAAgB,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB;iBACpD,CAAC,CAAA;gBACF,IAAI,WAAW,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;oBAC/B,GAAG,CAAC,IAAI,CAAC,2CAA2C,CAAC,CAAA;gBACvD,CAAC;gBACD,MAAM,CAAC,QAAQ,CACb,WAAW,CAAC,MAAM,EAClB,GAAG,EACH,kCAAkC,CACnC,CAAA;gBACD,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC;oBACvC,GAAG;oBACH,MAAM,EAAE,MAAM;oBACd,gBAAgB,EAAE,KAAK,CAAC,UAAU,CAAC,gBAAgB;iBACpD,CAAC,CAAA;gBACF,MAAM,CAAC,QAAQ,CACb,YAAY,CAAC,MAAM,EACnB,GAAG,EACH,kDAAkD,CACnD,CAAA;YACH,CAAC;SACF;QACD;YACE,EAAE,EAAE,gDAAgD;YACpD,IAAI,EACF,iEAAiE;gBACjE,SAAS;YACX,QAAQ,EAAE,IAAI;YACd,QAAQ,EAAE,CAAC,2DAA2D,CAAC;YACvE,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;gBACxB,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,CAAA;gBACvB,MAAM,GAAG,GAAG,IAAI,GAAG,CACjB,UAAU,KAAK,CAAC,MAAM,CAAC,EAAE,UAAU,EACnC,GAAG,CAAC,SAAS,CACd,CAAC,QAAQ,EAAE,CAAA;gBACZ,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;oBAChC,MAAM,EAAE,SAAS;oBACjB,OAAO,EAAE;wBACP,MAAM,EAAE,qBAAqB;wBAC7B,+BAA+B,EAAE,QAAQ;qBAC1C;iBACF,CAAC,CAAA;gBACF,MAAM,CAAC,QAAQ,CACb,QAAQ,CAAC,MAAM,EACf,GAAG,EACH,kEAAkE;oBAChE,SAAS,CACZ,CAAA;YACH,CAAC;SACF;KACF;CACF,CAAA"}
|
|
@@ -94,7 +94,7 @@ export const resourceApi = {
|
|
|
94
94
|
const { alice } = state;
|
|
95
95
|
try {
|
|
96
96
|
await alice.rootClient.request({
|
|
97
|
-
url: new URL(`/space/${alice.space1.id}
|
|
97
|
+
url: new URL(`/space/${alice.space1.id}/`, ctx.serverUrl).toString(),
|
|
98
98
|
method: 'DELETE'
|
|
99
99
|
});
|
|
100
100
|
}
|