@interop/was-client 0.66.0 → 0.67.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.
Files changed (95) hide show
  1. package/README.md +30 -28
  2. package/dist/Collection.d.ts +30 -41
  3. package/dist/Collection.d.ts.map +1 -1
  4. package/dist/Collection.js +35 -78
  5. package/dist/Collection.js.map +1 -1
  6. package/dist/Resource.d.ts +28 -41
  7. package/dist/Resource.d.ts.map +1 -1
  8. package/dist/Resource.js +29 -65
  9. package/dist/Resource.js.map +1 -1
  10. package/dist/Space.d.ts +14 -14
  11. package/dist/Space.d.ts.map +1 -1
  12. package/dist/Space.js +16 -16
  13. package/dist/Space.js.map +1 -1
  14. package/dist/WasClient.d.ts +3 -2
  15. package/dist/WasClient.d.ts.map +1 -1
  16. package/dist/WasClient.js +4 -7
  17. package/dist/WasClient.js.map +1 -1
  18. package/dist/codec.d.ts +2 -9
  19. package/dist/codec.d.ts.map +1 -1
  20. package/dist/codec.js +1 -1
  21. package/dist/codec.js.map +1 -1
  22. package/dist/edv/EdvCodec.d.ts +3 -3
  23. package/dist/edv/EdvCodec.d.ts.map +1 -1
  24. package/dist/edv/EdvCodec.js +22 -72
  25. package/dist/edv/EdvCodec.js.map +1 -1
  26. package/dist/edv/WasTransport.d.ts +30 -44
  27. package/dist/edv/WasTransport.d.ts.map +1 -1
  28. package/dist/edv/WasTransport.js +38 -119
  29. package/dist/edv/WasTransport.js.map +1 -1
  30. package/dist/edv/descriptorStore.d.ts +5 -7
  31. package/dist/edv/descriptorStore.d.ts.map +1 -1
  32. package/dist/edv/descriptorStore.js +3 -4
  33. package/dist/edv/descriptorStore.js.map +1 -1
  34. package/dist/edv/docCipher.d.ts +1 -2
  35. package/dist/edv/docCipher.d.ts.map +1 -1
  36. package/dist/edv/docCipher.js +1 -2
  37. package/dist/edv/docCipher.js.map +1 -1
  38. package/dist/edv/logGovernedDescriptorStore.d.ts.map +1 -1
  39. package/dist/edv/logGovernedDescriptorStore.js +1 -2
  40. package/dist/edv/logGovernedDescriptorStore.js.map +1 -1
  41. package/dist/errors.d.ts +7 -6
  42. package/dist/errors.d.ts.map +1 -1
  43. package/dist/errors.js +7 -6
  44. package/dist/errors.js.map +1 -1
  45. package/dist/index.d.ts +0 -1
  46. package/dist/index.d.ts.map +1 -1
  47. package/dist/index.js.map +1 -1
  48. package/dist/internal/cas.d.ts +19 -19
  49. package/dist/internal/cas.d.ts.map +1 -1
  50. package/dist/internal/cas.js +30 -23
  51. package/dist/internal/cas.js.map +1 -1
  52. package/dist/internal/conditional.d.ts +17 -63
  53. package/dist/internal/conditional.d.ts.map +1 -1
  54. package/dist/internal/conditional.js +20 -76
  55. package/dist/internal/conditional.js.map +1 -1
  56. package/dist/internal/memo.d.ts +2 -2
  57. package/dist/internal/memo.js +2 -2
  58. package/dist/internal/meta.d.ts +13 -29
  59. package/dist/internal/meta.d.ts.map +1 -1
  60. package/dist/internal/meta.js +22 -41
  61. package/dist/internal/meta.js.map +1 -1
  62. package/dist/internal/paths.d.ts +1 -1
  63. package/dist/internal/paths.js +1 -1
  64. package/dist/internal/request.d.ts +0 -10
  65. package/dist/internal/request.d.ts.map +1 -1
  66. package/dist/internal/request.js.map +1 -1
  67. package/dist/internal/write.d.ts +12 -36
  68. package/dist/internal/write.d.ts.map +1 -1
  69. package/dist/internal/write.js +16 -87
  70. package/dist/internal/write.js.map +1 -1
  71. package/dist/log/logStore.d.ts +6 -8
  72. package/dist/log/logStore.d.ts.map +1 -1
  73. package/dist/log/logStore.js +7 -10
  74. package/dist/log/logStore.js.map +1 -1
  75. package/dist/sync/index.d.ts +9 -5
  76. package/dist/sync/index.d.ts.map +1 -1
  77. package/dist/sync/index.js +9 -5
  78. package/dist/sync/index.js.map +1 -1
  79. package/dist/sync/port.d.ts +3 -7
  80. package/dist/sync/port.d.ts.map +1 -1
  81. package/dist/sync/port.js +4 -20
  82. package/dist/sync/port.js.map +1 -1
  83. package/dist/sync/predicates.d.ts +21 -2
  84. package/dist/sync/predicates.d.ts.map +1 -1
  85. package/dist/sync/predicates.js +23 -2
  86. package/dist/sync/predicates.js.map +1 -1
  87. package/dist/sync/types.d.ts +8 -9
  88. package/dist/sync/types.d.ts.map +1 -1
  89. package/dist/types.d.ts +4 -3
  90. package/dist/types.d.ts.map +1 -1
  91. package/package.json +3 -3
  92. package/dist/internal/features.d.ts +0 -111
  93. package/dist/internal/features.d.ts.map +0 -1
  94. package/dist/internal/features.js +0 -197
  95. package/dist/internal/features.js.map +0 -1
package/README.md CHANGED
@@ -217,7 +217,7 @@ info.version // '0.5'
217
217
  info.entry // the chosen `PwsVersionEntry`
218
218
  info.description // the whole `ServiceDescription`
219
219
  info.spacesUrl // the Spaces Repository URL, or undefined
220
- info.features // e.g. ['listing', 'collection-management', ...]
220
+ info.features // e.g. ['listing', 'collection-management', 'changes-query', ...]
221
221
  info.hasFeature('quotas') // false when the token is absent
222
222
 
223
223
  // Discover again, e.g. before relying on an affordance a host may have dropped.
@@ -611,7 +611,7 @@ await collection.setMeta({ custom: { name: 'Vault', tags: { app: 'wallet' } } })
611
611
  await collection.setName('Renamed vault') // keeps existing tags
612
612
  await collection.setTags({ app: 'wallet' }) // keeps existing name
613
613
 
614
- // Conditional metadata write, against a `conditional-writes` backend.
614
+ // Conditional metadata write.
615
615
  await collection.setMeta({ custom: { name: 'Vault' } }, { ifMatch: meta?.etag })
616
616
  // ...or create the Collection only if it does not exist yet:
617
617
  await collection.setMeta({ custom: { name: 'Vault' } }, { ifNoneMatch: true })
@@ -690,10 +690,10 @@ const { descriptor } = await store.read() // verified head state, `history` kept
690
690
 
691
691
  ### Conditional writes (optimistic concurrency)
692
692
 
693
- Against a backend that advertises the `conditional-writes` feature (see below),
694
- a Resource carries a strong **`ETag`** validator that changes on every write.
695
- Use it to prevent the lost-update problem -- two clients that both read version
696
- _N_ and each write _N+1_, the second silently clobbering the first.
693
+ Every Resource carries a strong **`ETag`** validator that changes on every write
694
+ (conditional writes are a baseline WAS server requirement). Use it to prevent
695
+ the lost-update problem -- two clients that both read version _N_ and each write
696
+ _N+1_, the second silently clobbering the first.
697
697
 
698
698
  ```ts
699
699
  const { etag } = await collection.put('doc', { v: 1 }) // writes return the ETag
@@ -740,20 +740,21 @@ const usage = await collection.quota() // BackendUsage | null
740
740
  // usage: { id, state, usageBytes, limit, restrictedActions, measuredAt, ... }
741
741
  ```
742
742
 
743
- A `BackendDescriptor`'s optional `features` array advertises optional **server
744
- affordances** -- things the backend actively does beyond the baseline read/write
745
- API (e.g. `conditional-writes`, `blinded-index-query`, `chunked-streams`). An
746
- absent token means the backend makes no claim to it, so treat it as unsupported
747
- rather than assuming a default. (Client-side encryption is _not_ a backend
748
- feature -- see below.)
743
+ A `BackendDescriptor` says where a Collection's data lives; it advertises no
744
+ optional affordances. Server-wide affordances are read from the service
745
+ description instead:
749
746
 
750
747
  ```ts
751
- const backend = await collection.backend()
752
- if (backend?.features?.includes('conditional-writes')) {
753
- // backend enforces If-Match / If-None-Match write preconditions
748
+ const info = await was.service()
749
+ if (info.hasFeature('changes-query')) {
750
+ // the server serves the replication change feed
754
751
  }
755
752
  ```
756
753
 
754
+ An absent token means the server makes no claim to it, so treat it as
755
+ unsupported rather than assuming a default. (Client-side encryption is _not_ a
756
+ server affordance -- see below.)
757
+
757
758
  ### Registering a Bring-Your-Own-Storage backend
758
759
 
759
760
  Beyond the server's built-in `default` backend, the Space controller can
@@ -768,7 +769,6 @@ const descriptor = await space.registerBackend({
768
769
  id: 'gdrive-personal', // unique within the Space
769
770
  name: 'My Google Drive',
770
771
  provider: 'google-drive', // selects the server-side adapter
771
- storageMode: ['document', 'blob'],
772
772
  connection: {
773
773
  kind: 'oauth2-google',
774
774
  authorizationCode: '4/0Ab...', // one-time PKCE code (or a refreshToken)
@@ -918,12 +918,13 @@ scope for now):
918
918
  - **Binary.** A `Blob`/`Uint8Array` up to `maxBlobBytes` (512 KiB by default) is
919
919
  encrypted as a single document. A larger one is routed automatically by
920
920
  `add()` to the chunked-stream path: one document plus its chunk resources,
921
- read back transparently by `get()`. That needs the backend's `chunked-streams`
922
- feature, checked before anything is written (`NotSupportedError` otherwise).
923
- Two limits apply. Auto-routing is an `add()` affordance -- `put(id, bigBlob)`
924
- is refused, since replacing an existing document's chunks is not automated.
925
- And a content-addressed collection (`idDerivation: 'content'`) is refused too:
926
- a chunked write stores the document twice, so no single ciphertext derives its
921
+ read back transparently by `get()`. Serving the chunk endpoints is a
922
+ conformance requirement of a server that offers encrypted collections, so
923
+ there is no client-side gate -- one that does not answers `501`. Two limits
924
+ apply. Auto-routing is an `add()` affordance -- `put(id, bigBlob)` is refused,
925
+ since replacing an existing document's chunks is not automated. And a
926
+ content-addressed collection (`idDerivation: 'content'`) is refused too: a
927
+ chunked write stores the document twice, so no single ciphertext derives its
927
928
  id. Tune the threshold and the chunk size with
928
929
  `createEdvEncryption({ maxBlobBytes, chunkSize })`.
929
930
  - **Raw reads.** `get()` decrypts; the `getText()` / `getBytes()` escape hatches
@@ -989,9 +990,10 @@ Two properties are worth planning around:
989
990
  an attribute the schema does not declare throws `ValidationError` rather than
990
991
  silently matching nothing.
991
992
 
992
- Requires the collection's backend to advertise `blinded-index-query`; a backend
993
- without it answers `501` (`NotImplementedError`). `find()` / `declareIndex()` on
994
- a plaintext collection throw -- there is no client-side index there.
993
+ Serving the blinded-index query profile is a conformance requirement of a server
994
+ that offers encrypted collections; one that does not answers `501`
995
+ (`NotImplementedError`). `find()` / `declareIndex()` on a plaintext collection
996
+ throw -- there is no client-side index there.
995
997
 
996
998
  Note that `collection.setMeta({ custom })` replaces the whole `custom` object,
997
999
  schema included; the `setName()` / `setTags()` sugar merges instead and leaves
@@ -1151,9 +1153,9 @@ re-exports none of them.
1151
1153
  governing history log" above). The store does read-with-etag of the full log,
1152
1154
  compare-and-swap append conditioned on that etag, and the guarded create of a
1153
1155
  genesis entry. Appends carry the prior lines' bytes forward verbatim. Both
1154
- writes ride the backend's `conditional-writes` feature, which the profile
1155
- requires; a lost race rethrows the library's `ResourceLogConflictError` with
1156
- the transport's `PreconditionFailedError` as `cause`.
1156
+ writes ride the server's conditional writes, which the profile requires; a
1157
+ lost race rethrows the library's `ResourceLogConflictError` with the
1158
+ transport's `PreconditionFailedError` as `cause`.
1157
1159
 
1158
1160
  ### Export and import
1159
1161
 
@@ -1,5 +1,4 @@
1
1
  import type { ClientContext } from './internal/request.js';
2
- import type { FeatureProbe } from './internal/features.js';
3
2
  import type { CodecRequestContext, IndexDeclaration, IndexSchema } from './codec.js';
4
3
  import { Resource } from './Resource.js';
5
4
  import type { ChangeDocument, ChangesCheckpoint, ChangesPage } from '@interop/storage-core';
@@ -26,19 +25,9 @@ export declare class Collection {
26
25
  capability?: IZcap;
27
26
  encryption?: EncryptionOverride;
28
27
  });
29
- /**
30
- * The memoized backend-feature probe this handle and its child resource
31
- * handles share. A store built over the handle (a history log store, the
32
- * sync port) gates its guarded writes on it without a second descriptor
33
- * read. Reading it performs no I/O.
34
- *
35
- * @returns {FeatureProbe}
36
- */
37
- get features(): FeatureProbe;
38
28
  /**
39
29
  * The signed-request context handed to a codec that drives its own I/O (the
40
- * EDV codec reading a chunked blob back), bound to this handle's capability
41
- * and sharing its memoized feature probe.
30
+ * EDV codec reading a chunked blob back), bound to this handle's capability.
42
31
  *
43
32
  * Public so a sync replica can pass it to `DocCipher.decrypt`, which then
44
33
  * reassembles a chunked envelope from its chunk resources on this
@@ -191,7 +180,7 @@ export declare class Collection {
191
180
  * no keys for, which is why {@link describe} -- the configuration read -- goes
192
181
  * without it.
193
182
  *
194
- * Against a backend with the `conditional-writes` feature the result also
183
+ * The result also
195
184
  * carries the object's current `etag` (its `metaVersion` validator) -- pass it
196
185
  * as `setMeta(meta, { ifMatch })` for a lost-update-safe update. One
197
186
  * validator covers the whole object: a configuration write and an annotation
@@ -217,8 +206,8 @@ export declare class Collection {
217
206
  * and encrypted collections alike. The key epoch the codec stamps the
218
207
  * envelope with travels as a top-level `epoch` member of the same body.
219
208
  *
220
- * Conditional writes (the backend's `conditional-writes` feature): pass
221
- * `ifMatch` (the `etag` from a prior {@link meta} or {@link describe}) for an
209
+ * Conditional writes: pass `ifMatch` (the `etag` from a prior {@link meta}
210
+ * or {@link describe}) for an
222
211
  * update-if-unchanged, and a failed precondition throws
223
212
  * `PreconditionFailedError` (412). Without one the write is pinned to the
224
213
  * version it composed the configuration from and rebases on a lost race.
@@ -254,11 +243,10 @@ export declare class Collection {
254
243
  /**
255
244
  * Sets the Collection's annotation-level human-readable `name`, preserving
256
245
  * any existing `tags`. Convenience over `setMeta()`. The write is pinned to
257
- * the `etag` the `meta()` read returned (when the backend supports
258
- * `conditional-writes`) and rebases on a lost race, so a concurrent write --
259
- * an annotation write or a configuration change, which share the one
260
- * validator -- is re-read and re-applied rather than silently erased by this
261
- * full-replacement write.
246
+ * the `etag` the `meta()` read returned and rebases on a lost race, so a
247
+ * concurrent write -- an annotation write or a configuration change, which
248
+ * share the one validator -- is re-read and re-applied rather than silently
249
+ * erased by this full-replacement write.
262
250
  *
263
251
  * On an encrypted collection this is the collection's client-encrypted name
264
252
  * surface: the codec seals it into the `custom` envelope, and by convention
@@ -290,8 +278,8 @@ export declare class Collection {
290
278
  */
291
279
  get historyLogUrl(): string;
292
280
  /**
293
- * Reads the Collection's governing history log (the backend's
294
- * `governed-history-logs` feature): the JSON Lines body served at the
281
+ * Reads the Collection's governing history log (the encrypted-collections
282
+ * profile's `governed-history-logs` feature): the JSON Lines body served at the
295
283
  * `/meta/log` sub-resource, verbatim, together with its `ETag`. The log is
296
284
  * not a Resource of the Collection (absent from listings and the `changes`
297
285
  * feed) and not part of the `/meta` object; it is versioned by its own
@@ -434,8 +422,10 @@ export declare class Collection {
434
422
  * one page: `limit` caps its size (the server clamps its own maximum), and a
435
423
  * `hasMore` page carries the `cursor` to pass back for the next one.
436
424
  *
437
- * Requires the collection's backend to advertise the `blinded-index-query`
438
- * feature; a backend without it answers `501` (`NotImplementedError`).
425
+ * Serving the blinded-index query profile is a conformance requirement of a
426
+ * server that offers encrypted collections, so there is no client-side
427
+ * probe; a server that does not implement it answers `501`
428
+ * (`NotImplementedError`).
439
429
  *
440
430
  * @param options {object}
441
431
  * @param [options.equals] {object | object[]} attribute/value pairs to match
@@ -473,8 +463,7 @@ export declare class Collection {
473
463
  *
474
464
  * On an encrypted collection a binary payload above the codec's
475
465
  * single-document threshold is auto-routed to the chunked-stream path, which
476
- * needs the backend's `chunked-streams` feature (`NotSupportedError` without
477
- * it, raised before anything is written).
466
+ * a server that does not serve the chunk endpoints answers with `501`.
478
467
  *
479
468
  * @param data {ResourceData}
480
469
  * @param options {object}
@@ -496,7 +485,7 @@ export declare class Collection {
496
485
  /**
497
486
  * Creates or replaces a resource by id (upsert). Forwards the
498
487
  * conditional-write options (`ifMatch` / `ifNoneMatch`) to `Resource.put`;
499
- * see it for the `conditional-writes` semantics. Returns the stored
488
+ * see it for the conditional-write semantics. Returns the stored
500
489
  * resource's new `etag`.
501
490
  *
502
491
  * @param resourceId {string}
@@ -559,11 +548,11 @@ export declare class Collection {
559
548
  * `limit` to its own maximum, so a short page can still be a full server
560
549
  * page.
561
550
  *
562
- * Requires the collection's backend to advertise the `changes-query` feature
563
- * (see `backend()`); a backend without it answers `501`. On an encrypted
564
- * collection the documents' `data` / `custom` are the scheme's opaque
565
- * envelopes (an EDV encrypted document under the v1 `edv` scheme) -- this
566
- * method does not decrypt them, unlike `get()`.
551
+ * Requires the server to advertise the `changes-query` feature server-wide
552
+ * (`client.service().features`); a server without it answers `501`. On an
553
+ * encrypted collection the documents' `data` / `custom` are the scheme's
554
+ * opaque envelopes (an EDV encrypted document under the v1 `edv` scheme) --
555
+ * this method does not decrypt them, unlike `get()`.
567
556
  *
568
557
  * Malformed responses fail the call with a `WasServerError` instead of
569
558
  * passing through as a page: a 2xx response with no JSON body
@@ -600,9 +589,10 @@ export declare class Collection {
600
589
  * `list()`. Unlike `list()`, a 404 on a later page throws: the collection
601
590
  * vanished mid-walk, and the pages already read are not a snapshot of
602
591
  * anything. The server faults `changes()` rejects on (a bodiless 2xx, a
603
- * live entry with no `data`, or a `501` from a backend without the
604
- * `changes-query` feature) fail the walk with the same `WasServerError`, as
605
- * does a server that repeats a checkpoint instead of advancing.
592
+ * live entry with no `data`, or a `501` from a server that does not
593
+ * advertise the `changes-query` feature) fail the walk with the same
594
+ * `WasServerError`, as does a server that repeats a checkpoint instead of
595
+ * advancing.
606
596
  *
607
597
  * @param [options] {object}
608
598
  * @param [options.limit] {number} max documents per request (default 1000, the teaching server's maximum); the server reduces it to its own maximum
@@ -671,12 +661,11 @@ export declare class Collection {
671
661
  * you (404 conflation caveat). A server without backend support surfaces its
672
662
  * 501 as `NotImplementedError`.
673
663
  *
674
- * The descriptor's optional `features` array advertises optional server
675
- * affordances (e.g. `conditional-writes`, `blinded-index-query`,
676
- * `chunked-streams`); an absent token means the backend makes no claim to it,
677
- * so treat it as unsupported rather than assuming a default. (Client-side
678
- * encryption is not a backend feature -- it is a per-collection client concern
679
- * gated on the client's keys.)
664
+ * The descriptor names where the collection is stored; it advertises no
665
+ * optional affordances. Server-wide affordance tokens live in the service
666
+ * description (`client.service().features`). (Client-side encryption is
667
+ * neither -- it is a per-collection client concern gated on the client's
668
+ * keys.)
680
669
  *
681
670
  * @returns {Promise<BackendDescriptor | null>}
682
671
  */
@@ -1 +1 @@
1
- {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"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"}
@@ -21,7 +21,6 @@ import { NotFoundError, ValidationError, WasServerError, httpStatus } from './er
21
21
  import { delegateGrantAt } from './internal/grant.js';
22
22
  import { send, readData } from './internal/request.js';
23
23
  import { codecForDescriptor, collectionCodecHolder, identityCodec } from './internal/codec.js';
24
- import { collectionBackendFeatures } from './internal/features.js';
25
24
  import { collectWalk, signedPageWalk, walkItems, walkPagesOrEmpty } from './internal/pagination.js';
26
25
  import { ANNOTATION_MEMBERS, CONFIGURATION_MEMBERS, asCollectionMetadata, carriedForward, collectionWritableFields, isGovernedDescriptor, readCollectionMetadata, storedEncryption, unreadableDescriptionError } from './internal/describe.js';
27
26
  import { assertSinglePrecondition, readEtag, writeHeaders } from './internal/conditional.js';
@@ -84,12 +83,6 @@ export class Collection {
84
83
  * without discovering a descriptor from stored state.
85
84
  */
86
85
  #encryptionOverride;
87
- /**
88
- * The shared backend-feature probe for this collection (memoized on a
89
- * definitive answer), consulted by the conditional-codec write path and
90
- * shared with child resource handles the way the codec is.
91
- */
92
- #features;
93
86
  /**
94
87
  * @param options {object}
95
88
  * @param options.context {ClientContext} - Shared context (serverUrl, ezcap
@@ -123,11 +116,6 @@ export class Collection {
123
116
  override: encryption,
124
117
  capability
125
118
  });
126
- this.#features = collectionBackendFeatures(context, {
127
- spaceId,
128
- collectionId,
129
- capability
130
- });
131
119
  }
132
120
  /**
133
121
  * The Collection container in canonical (trailing-slash) form: the URL whose
@@ -141,21 +129,9 @@ export class Collection {
141
129
  get #policyPath() {
142
130
  return collectionPolicy(this.spaceId, this.id);
143
131
  }
144
- /**
145
- * The memoized backend-feature probe this handle and its child resource
146
- * handles share. A store built over the handle (a history log store, the
147
- * sync port) gates its guarded writes on it without a second descriptor
148
- * read. Reading it performs no I/O.
149
- *
150
- * @returns {FeatureProbe}
151
- */
152
- get features() {
153
- return this.#features;
154
- }
155
132
  /**
156
133
  * The signed-request context handed to a codec that drives its own I/O (the
157
- * EDV codec reading a chunked blob back), bound to this handle's capability
158
- * and sharing its memoized feature probe.
134
+ * EDV codec reading a chunked blob back), bound to this handle's capability.
159
135
  *
160
136
  * Public so a sync replica can pass it to `DocCipher.decrypt`, which then
161
137
  * reassembles a chunked envelope from its chunk resources on this
@@ -164,10 +140,7 @@ export class Collection {
164
140
  * @returns {CodecRequestContext}
165
141
  */
166
142
  codecContext() {
167
- return codecRequestContext(this.#context, {
168
- features: this.#features,
169
- capability: this.#capability
170
- });
143
+ return codecRequestContext(this.#context, { capability: this.#capability });
171
144
  }
172
145
  /**
173
146
  * Resolves (once, then caches) the codec for this collection's reads and
@@ -309,17 +282,7 @@ export class Collection {
309
282
  * compare-and-swap attempt limit. One validator covers configuration and
310
283
  * annotations alike, so a configuration change now legitimately invalidates
311
284
  * an in-flight annotation write; rebasing is the normal outcome, not an
312
- * error. A backend without `conditional-writes` serves no validator, and
313
- * the write stays the unconditional upsert it has always been.
314
- *
315
- * Limitation, on a backend without `conditional-writes` only: the body
316
- * re-sends the stored `encryption` descriptor, and with no validator to pin
317
- * the `PUT` to, a descriptor rotation landing between the compose read and
318
- * the write is re-sent as the older roster -- refused as a spurious
319
- * `invalid-request-body` ("epochs is append-only") by a server enforcing the
320
- * descriptor invariants, and rolled back by one that does not. There is no
321
- * client-side remedy without a validator or a partial-update form, neither of
322
- * which WAS v0.5 offers (WCL-99).
285
+ * error.
323
286
  *
324
287
  * The absent-object rule is the masked-404 fail-closed policy at write level:
325
288
  * a `null` read means "missing OR not visible to you", and composing against
@@ -337,8 +300,7 @@ export class Collection {
337
300
  * @param [options.current] {object} an object the caller has already read,
338
301
  * used as the first attempt's baseline instead of re-reading it: the write
339
302
  * composes against it and pins to its validator, and a rebase re-reads. A
340
- * baseline carrying no validator makes the first attempt unconditional,
341
- * which is what a backend without `conditional-writes` offers anyway
303
+ * baseline carrying no validator is refused by the compare-and-swap loop
342
304
  * @param [options.allowAbsent] {boolean} compose against nothing (an
343
305
  * upsert) instead of throwing `NotFoundError` when the object cannot be
344
306
  * read
@@ -714,7 +676,7 @@ export class Collection {
714
676
  * no keys for, which is why {@link describe} -- the configuration read -- goes
715
677
  * without it.
716
678
  *
717
- * Against a backend with the `conditional-writes` feature the result also
679
+ * The result also
718
680
  * carries the object's current `etag` (its `metaVersion` validator) -- pass it
719
681
  * as `setMeta(meta, { ifMatch })` for a lost-update-safe update. One
720
682
  * validator covers the whole object: a configuration write and an annotation
@@ -762,8 +724,8 @@ export class Collection {
762
724
  * and encrypted collections alike. The key epoch the codec stamps the
763
725
  * envelope with travels as a top-level `epoch` member of the same body.
764
726
  *
765
- * Conditional writes (the backend's `conditional-writes` feature): pass
766
- * `ifMatch` (the `etag` from a prior {@link meta} or {@link describe}) for an
727
+ * Conditional writes: pass `ifMatch` (the `etag` from a prior {@link meta}
728
+ * or {@link describe}) for an
767
729
  * update-if-unchanged, and a failed precondition throws
768
730
  * `PreconditionFailedError` (412). Without one the write is pinned to the
769
731
  * version it composed the configuration from and rebases on a lost race.
@@ -838,11 +800,10 @@ export class Collection {
838
800
  /**
839
801
  * Sets the Collection's annotation-level human-readable `name`, preserving
840
802
  * any existing `tags`. Convenience over `setMeta()`. The write is pinned to
841
- * the `etag` the `meta()` read returned (when the backend supports
842
- * `conditional-writes`) and rebases on a lost race, so a concurrent write --
843
- * an annotation write or a configuration change, which share the one
844
- * validator -- is re-read and re-applied rather than silently erased by this
845
- * full-replacement write.
803
+ * the `etag` the `meta()` read returned and rebases on a lost race, so a
804
+ * concurrent write -- an annotation write or a configuration change, which
805
+ * share the one validator -- is re-read and re-applied rather than silently
806
+ * erased by this full-replacement write.
846
807
  *
847
808
  * On an encrypted collection this is the collection's client-encrypted name
848
809
  * surface: the codec seals it into the `custom` envelope, and by convention
@@ -883,8 +844,8 @@ export class Collection {
883
844
  return toUrl({ serverUrl: this.#context.serverUrl, path: this.#logPath });
884
845
  }
885
846
  /**
886
- * Reads the Collection's governing history log (the backend's
887
- * `governed-history-logs` feature): the JSON Lines body served at the
847
+ * Reads the Collection's governing history log (the encrypted-collections
848
+ * profile's `governed-history-logs` feature): the JSON Lines body served at the
888
849
  * `/meta/log` sub-resource, verbatim, together with its `ETag`. The log is
889
850
  * not a Resource of the Collection (absent from listings and the `changes`
890
851
  * feed) and not part of the `/meta` object; it is versioned by its own
@@ -1143,8 +1104,10 @@ export class Collection {
1143
1104
  * one page: `limit` caps its size (the server clamps its own maximum), and a
1144
1105
  * `hasMore` page carries the `cursor` to pass back for the next one.
1145
1106
  *
1146
- * Requires the collection's backend to advertise the `blinded-index-query`
1147
- * feature; a backend without it answers `501` (`NotImplementedError`).
1107
+ * Serving the blinded-index query profile is a conformance requirement of a
1108
+ * server that offers encrypted collections, so there is no client-side
1109
+ * probe; a server that does not implement it answers `501`
1110
+ * (`NotImplementedError`).
1148
1111
  *
1149
1112
  * @param options {object}
1150
1113
  * @param [options.equals] {object | object[]} attribute/value pairs to match
@@ -1164,9 +1127,8 @@ export class Collection {
1164
1127
  method: 'POST',
1165
1128
  capability: this.#capability,
1166
1129
  // The profile is bound here the way `changes()` binds its own: same
1167
- // endpoint, no client-side feature probe -- a backend that does not
1168
- // implement the profile answers 501, which is a clearer signal than a
1169
- // guess made from the backend descriptor.
1130
+ // endpoint, no client-side gate -- a server that does not implement the
1131
+ // profile answers 501.
1170
1132
  json: {
1171
1133
  profile: 'blinded-index',
1172
1134
  ...query,
@@ -1226,9 +1188,6 @@ export class Collection {
1226
1188
  collectionId: this.id,
1227
1189
  resourceId,
1228
1190
  capability: options.capability ?? this.#capability,
1229
- // Share this collection's memoized feature probe so per-resource handles
1230
- // do not each repeat the backend-descriptor round-trip.
1231
- features: this.#features,
1232
1191
  // A per-resource encryption override resolves its own codec (honoring the
1233
1192
  // override); without one, share this collection's resolved codec so the
1234
1193
  // resource handle does not repeat the descriptor-discovery round-trip.
@@ -1246,8 +1205,7 @@ export class Collection {
1246
1205
  *
1247
1206
  * On an encrypted collection a binary payload above the codec's
1248
1207
  * single-document threshold is auto-routed to the chunked-stream path, which
1249
- * needs the backend's `chunked-streams` feature (`NotSupportedError` without
1250
- * it, raised before anything is written).
1208
+ * a server that does not serve the chunk endpoints answers with `501`.
1251
1209
  *
1252
1210
  * @param data {ResourceData}
1253
1211
  * @param options {object}
@@ -1262,7 +1220,6 @@ export class Collection {
1262
1220
  pathForId: mintedId => resourcePath(this.spaceId, this.id, mintedId),
1263
1221
  codec,
1264
1222
  data,
1265
- features: this.#features,
1266
1223
  contentType: options.contentType,
1267
1224
  capability: this.#capability
1268
1225
  });
@@ -1330,7 +1287,7 @@ export class Collection {
1330
1287
  /**
1331
1288
  * Creates or replaces a resource by id (upsert). Forwards the
1332
1289
  * conditional-write options (`ifMatch` / `ifNoneMatch`) to `Resource.put`;
1333
- * see it for the `conditional-writes` semantics. Returns the stored
1290
+ * see it for the conditional-write semantics. Returns the stored
1334
1291
  * resource's new `etag`.
1335
1292
  *
1336
1293
  * @param resourceId {string}
@@ -1411,11 +1368,11 @@ export class Collection {
1411
1368
  * `limit` to its own maximum, so a short page can still be a full server
1412
1369
  * page.
1413
1370
  *
1414
- * Requires the collection's backend to advertise the `changes-query` feature
1415
- * (see `backend()`); a backend without it answers `501`. On an encrypted
1416
- * collection the documents' `data` / `custom` are the scheme's opaque
1417
- * envelopes (an EDV encrypted document under the v1 `edv` scheme) -- this
1418
- * method does not decrypt them, unlike `get()`.
1371
+ * Requires the server to advertise the `changes-query` feature server-wide
1372
+ * (`client.service().features`); a server without it answers `501`. On an
1373
+ * encrypted collection the documents' `data` / `custom` are the scheme's
1374
+ * opaque envelopes (an EDV encrypted document under the v1 `edv` scheme) --
1375
+ * this method does not decrypt them, unlike `get()`.
1419
1376
  *
1420
1377
  * Malformed responses fail the call with a `WasServerError` instead of
1421
1378
  * passing through as a page: a 2xx response with no JSON body
@@ -1493,9 +1450,10 @@ export class Collection {
1493
1450
  * `list()`. Unlike `list()`, a 404 on a later page throws: the collection
1494
1451
  * vanished mid-walk, and the pages already read are not a snapshot of
1495
1452
  * anything. The server faults `changes()` rejects on (a bodiless 2xx, a
1496
- * live entry with no `data`, or a `501` from a backend without the
1497
- * `changes-query` feature) fail the walk with the same `WasServerError`, as
1498
- * does a server that repeats a checkpoint instead of advancing.
1453
+ * live entry with no `data`, or a `501` from a server that does not
1454
+ * advertise the `changes-query` feature) fail the walk with the same
1455
+ * `WasServerError`, as does a server that repeats a checkpoint instead of
1456
+ * advancing.
1499
1457
  *
1500
1458
  * @param [options] {object}
1501
1459
  * @param [options.limit] {number} max documents per request (default 1000, the teaching server's maximum); the server reduces it to its own maximum
@@ -1637,12 +1595,11 @@ export class Collection {
1637
1595
  * you (404 conflation caveat). A server without backend support surfaces its
1638
1596
  * 501 as `NotImplementedError`.
1639
1597
  *
1640
- * The descriptor's optional `features` array advertises optional server
1641
- * affordances (e.g. `conditional-writes`, `blinded-index-query`,
1642
- * `chunked-streams`); an absent token means the backend makes no claim to it,
1643
- * so treat it as unsupported rather than assuming a default. (Client-side
1644
- * encryption is not a backend feature -- it is a per-collection client concern
1645
- * gated on the client's keys.)
1598
+ * The descriptor names where the collection is stored; it advertises no
1599
+ * optional affordances. Server-wide affordance tokens live in the service
1600
+ * description (`client.service().features`). (Client-side encryption is
1601
+ * neither -- it is a per-collection client concern gated on the client's
1602
+ * keys.)
1646
1603
  *
1647
1604
  * @returns {Promise<BackendDescriptor | null>}
1648
1605
  */