@interop/was-client 0.65.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 (99) hide show
  1. package/README.md +59 -50
  2. package/dist/Collection.d.ts +41 -30
  3. package/dist/Collection.d.ts.map +1 -1
  4. package/dist/Collection.js +41 -69
  5. package/dist/Collection.js.map +1 -1
  6. package/dist/Resource.d.ts +28 -37
  7. package/dist/Resource.d.ts.map +1 -1
  8. package/dist/Resource.js +26 -52
  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 +3 -2
  17. package/dist/WasClient.js.map +1 -1
  18. package/dist/codec.d.ts +8 -14
  19. package/dist/codec.d.ts.map +1 -1
  20. package/dist/codec.js.map +1 -1
  21. package/dist/edv/EdvCodec.d.ts +3 -3
  22. package/dist/edv/EdvCodec.d.ts.map +1 -1
  23. package/dist/edv/EdvCodec.js +25 -74
  24. package/dist/edv/EdvCodec.js.map +1 -1
  25. package/dist/edv/WasTransport.d.ts +30 -44
  26. package/dist/edv/WasTransport.d.ts.map +1 -1
  27. package/dist/edv/WasTransport.js +38 -119
  28. package/dist/edv/WasTransport.js.map +1 -1
  29. package/dist/edv/descriptorStore.d.ts +13 -12
  30. package/dist/edv/descriptorStore.d.ts.map +1 -1
  31. package/dist/edv/descriptorStore.js +7 -6
  32. package/dist/edv/descriptorStore.js.map +1 -1
  33. package/dist/edv/docCipher.d.ts +10 -1
  34. package/dist/edv/docCipher.d.ts.map +1 -1
  35. package/dist/edv/docCipher.js +23 -6
  36. package/dist/edv/docCipher.js.map +1 -1
  37. package/dist/edv/logGovernedDescriptorStore.d.ts.map +1 -1
  38. package/dist/edv/logGovernedDescriptorStore.js +4 -2
  39. package/dist/edv/logGovernedDescriptorStore.js.map +1 -1
  40. package/dist/edv/refreshingDocCipher.d.ts +4 -1
  41. package/dist/edv/refreshingDocCipher.d.ts.map +1 -1
  42. package/dist/edv/refreshingDocCipher.js +7 -4
  43. package/dist/edv/refreshingDocCipher.js.map +1 -1
  44. package/dist/errors.d.ts +24 -7
  45. package/dist/errors.d.ts.map +1 -1
  46. package/dist/errors.js +27 -7
  47. package/dist/errors.js.map +1 -1
  48. package/dist/index.d.ts +0 -1
  49. package/dist/index.d.ts.map +1 -1
  50. package/dist/index.js.map +1 -1
  51. package/dist/internal/cas.d.ts +22 -10
  52. package/dist/internal/cas.d.ts.map +1 -1
  53. package/dist/internal/cas.js +37 -11
  54. package/dist/internal/cas.js.map +1 -1
  55. package/dist/internal/conditional.d.ts +29 -8
  56. package/dist/internal/conditional.d.ts.map +1 -1
  57. package/dist/internal/conditional.js +30 -6
  58. package/dist/internal/conditional.js.map +1 -1
  59. package/dist/internal/memo.d.ts +2 -2
  60. package/dist/internal/memo.js +2 -2
  61. package/dist/internal/meta.d.ts +12 -10
  62. package/dist/internal/meta.d.ts.map +1 -1
  63. package/dist/internal/meta.js +20 -13
  64. package/dist/internal/meta.js.map +1 -1
  65. package/dist/internal/paths.d.ts +1 -1
  66. package/dist/internal/paths.js +1 -1
  67. package/dist/internal/write.d.ts +12 -29
  68. package/dist/internal/write.d.ts.map +1 -1
  69. package/dist/internal/write.js +15 -74
  70. package/dist/internal/write.js.map +1 -1
  71. package/dist/log/logStore.d.ts +10 -6
  72. package/dist/log/logStore.d.ts.map +1 -1
  73. package/dist/log/logStore.js +16 -6
  74. package/dist/log/logStore.js.map +1 -1
  75. package/dist/sync/index.d.ts +12 -5
  76. package/dist/sync/index.d.ts.map +1 -1
  77. package/dist/sync/index.js +12 -5
  78. package/dist/sync/index.js.map +1 -1
  79. package/dist/sync/plaintextCipher.d.ts +6 -4
  80. package/dist/sync/plaintextCipher.d.ts.map +1 -1
  81. package/dist/sync/plaintextCipher.js +19 -6
  82. package/dist/sync/plaintextCipher.js.map +1 -1
  83. package/dist/sync/port.d.ts +3 -1
  84. package/dist/sync/port.d.ts.map +1 -1
  85. package/dist/sync/port.js +3 -3
  86. package/dist/sync/port.js.map +1 -1
  87. package/dist/sync/predicates.d.ts +33 -3
  88. package/dist/sync/predicates.d.ts.map +1 -1
  89. package/dist/sync/predicates.js +37 -3
  90. package/dist/sync/predicates.js.map +1 -1
  91. package/dist/sync/types.d.ts +24 -5
  92. package/dist/sync/types.d.ts.map +1 -1
  93. package/dist/types.d.ts +4 -3
  94. package/dist/types.d.ts.map +1 -1
  95. package/package.json +3 -3
  96. package/dist/internal/features.d.ts +0 -105
  97. package/dist/internal/features.d.ts.map +0 -1
  98. package/dist/internal/features.js +0 -168
  99. 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
@@ -1017,31 +1019,38 @@ plugs into:
1017
1019
  failure arrives as the typed `WasError` subclass for its status, carrying the
1018
1020
  server's `problem+json` fields.
1019
1021
  - **`isSyncConflictError` / `isSyncNotFoundError` / `isSyncAuthError` /
1020
- `isUnknownEpochError` / `isKeyUnwrapError`** classify those signals by
1021
- `err.name`. Use them rather than `instanceof`: the port and the `DocCipher`
1022
- are seams your app injects, and a tree that resolves two copies of this
1023
- package makes an `instanceof` check quietly false. Read what you need off the
1024
- matched value, such as `err.status` on an auth error to tell a 401 from the
1025
- masked 404. The last two tell a decrypt's two no-key outcomes apart: an epoch
1026
- the reader's descriptor does not list (a re-read may fix it) and an epoch it
1027
- lists but this reader holds no key for (real data, permanently unreadable
1028
- here, never garbage).
1022
+ `isUnknownEpochError` / `isKeyUnwrapError` / `isIntegrityError`** classify
1023
+ those signals by `err.name`. Use them rather than `instanceof`: the port and
1024
+ the `DocCipher` are seams your app injects, and a tree that resolves two
1025
+ copies of this package makes an `instanceof` check quietly false. Read what
1026
+ you need off the matched value, such as `err.status` on an auth error to tell
1027
+ a 401 from the masked 404. The last two tell a decrypt's two no-key outcomes
1028
+ apart: an epoch the reader's descriptor does not list (a re-read may fix it)
1029
+ and an epoch it lists but this reader holds no key for (real data, permanently
1030
+ unreadable here, never garbage). `isIntegrityError` matches a stored body that
1031
+ does not verify against the resource id it was read under. Do not apply that
1032
+ row.
1029
1033
  - **`SyncStatus`** (`'idle' | 'syncing' | 'synced' | 'error'`) is the closed
1030
1034
  vocabulary a replication driver reports one feed's state through.
1031
1035
  - **`DocCipher`** is the per-collection encrypt/decrypt seam sitting above the
1032
1036
  port: it turns a JSON document into its stored body (minting the resource id)
1033
- and back. `createPlaintextDocCipher(...)` is the crypto-free identity
1034
- implementation for a plaintext content-addressed collection;
1035
- `createEdvDocCipher(...)` (from `@interop/was-client/edv`) is the encrypting
1036
- one, built from the collection's key-epoch descriptor (every encrypted
1037
- collection carries one from birth; install epoch[0] at provision time with
1038
- `ensureFirstEpoch`). On a searchable collection, also hand it the stored
1039
- Collection `/meta` value (the `meta` input, or `applyMeta` when the replica's
1040
- copy changes) so pushed documents carry blinded index entries and stay visible
1041
- to `find()`. `createEdvEncryptOnlyDocCipher(...)` is the write-only
1042
- counterpart, built from the descriptor alone with no key-agreement secret
1043
- (writes seal to the current epoch's public key, reconstructed from the epoch
1044
- id); `decrypt` on it refuses with the typed `EncryptOnlyCipherError`.
1037
+ and back. `decrypt({ id, envelope, context? })` takes the resource id the
1038
+ replica read the body under (the feed row's `id`, not the envelope's own) and
1039
+ throws `IntegrityError` when the body was written for a different id. Pass
1040
+ `collection.codecContext()` as `context` to read a chunked encrypted blob,
1041
+ which then decrypts to a `Blob`. `createPlaintextDocCipher(...)` is the
1042
+ crypto-free identity implementation for a plaintext content-addressed
1043
+ collection; `createEdvDocCipher(...)` (from `@interop/was-client/edv`) is the
1044
+ encrypting one, built from the collection's key-epoch descriptor (every
1045
+ encrypted collection carries one from birth; install epoch[0] at provision
1046
+ time with `ensureFirstEpoch`). Build it with the collection's `spaceId` to let
1047
+ `decrypt` fetch a chunked blob's chunks. On a searchable collection, also hand
1048
+ it the stored Collection `/meta` value (the `meta` input, or `applyMeta` when
1049
+ the replica's copy changes) so pushed documents carry blinded index entries
1050
+ and stay visible to `find()`. `createEdvEncryptOnlyDocCipher(...)` is the
1051
+ write-only counterpart, built from the descriptor alone with no key-agreement
1052
+ secret (writes seal to the current epoch's public key, reconstructed from the
1053
+ epoch id); `decrypt` on it refuses with the typed `EncryptOnlyCipherError`.
1045
1054
  - **`createRefreshingEdvDocCipher(...)`** (from `@interop/was-client/edv`) is
1046
1055
  `createEdvDocCipher` bound to descriptor acquisition and the unknown-epoch
1047
1056
  refresh rule: it acquires the collection's descriptor through the
@@ -1108,7 +1117,7 @@ do {
1108
1117
  const page = await port.query({ checkpoint, limit: 100 })
1109
1118
  for (const doc of page.documents) {
1110
1119
  if (doc._deleted) continue // tombstone
1111
- const data = await cipher.decrypt({ envelope: doc.data })
1120
+ const data = await cipher.decrypt({ id: doc.id, envelope: doc.data })
1112
1121
  // apply to the local replica, recording doc.version for later pushes
1113
1122
  }
1114
1123
  checkpoint = page.checkpoint // null when the page was empty (caught up)
@@ -1144,9 +1153,9 @@ re-exports none of them.
1144
1153
  governing history log" above). The store does read-with-etag of the full log,
1145
1154
  compare-and-swap append conditioned on that etag, and the guarded create of a
1146
1155
  genesis entry. Appends carry the prior lines' bytes forward verbatim. Both
1147
- writes ride the backend's `conditional-writes` feature, which the profile
1148
- requires; a lost race rethrows the library's `ResourceLogConflictError` with
1149
- 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`.
1150
1159
 
1151
1160
  ### Export and import
1152
1161
 
@@ -1,5 +1,5 @@
1
1
  import type { ClientContext } from './internal/request.js';
2
- import type { IndexDeclaration, IndexSchema } from './codec.js';
2
+ import type { CodecRequestContext, IndexDeclaration, IndexSchema } from './codec.js';
3
3
  import { Resource } from './Resource.js';
4
4
  import type { ChangeDocument, ChangesCheckpoint, ChangesPage } from '@interop/storage-core';
5
5
  import type { AddResult, BackendDescriptor, BackendUsage, CollectionMetadata, CollectionWritableFields, EncryptionOverride, FindPage, GrantOptions, HandleOptions, IDelegatedZcap, IZcap, Json, ResourceData, LinkSet, PolicyDocument, CollectionResourcesList, ResourceMetadataCustomInput, ResourceSummary } from './types.js';
@@ -25,6 +25,17 @@ export declare class Collection {
25
25
  capability?: IZcap;
26
26
  encryption?: EncryptionOverride;
27
27
  });
28
+ /**
29
+ * The signed-request context handed to a codec that drives its own I/O (the
30
+ * EDV codec reading a chunked blob back), bound to this handle's capability.
31
+ *
32
+ * Public so a sync replica can pass it to `DocCipher.decrypt`, which then
33
+ * reassembles a chunked envelope from its chunk resources on this
34
+ * collection. Building it performs no I/O.
35
+ *
36
+ * @returns {CodecRequestContext}
37
+ */
38
+ codecContext(): CodecRequestContext;
28
39
  /**
29
40
  * Reads the Collection Metadata object -- the Collection's configuration
30
41
  * (`name`, `backend`, `encryption`, `generator`) beside the server-managed
@@ -169,7 +180,7 @@ export declare class Collection {
169
180
  * no keys for, which is why {@link describe} -- the configuration read -- goes
170
181
  * without it.
171
182
  *
172
- * Against a backend with the `conditional-writes` feature the result also
183
+ * The result also
173
184
  * carries the object's current `etag` (its `metaVersion` validator) -- pass it
174
185
  * as `setMeta(meta, { ifMatch })` for a lost-update-safe update. One
175
186
  * validator covers the whole object: a configuration write and an annotation
@@ -195,8 +206,8 @@ export declare class Collection {
195
206
  * and encrypted collections alike. The key epoch the codec stamps the
196
207
  * envelope with travels as a top-level `epoch` member of the same body.
197
208
  *
198
- * Conditional writes (the backend's `conditional-writes` feature): pass
199
- * `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
200
211
  * update-if-unchanged, and a failed precondition throws
201
212
  * `PreconditionFailedError` (412). Without one the write is pinned to the
202
213
  * version it composed the configuration from and rebases on a lost race.
@@ -232,11 +243,10 @@ export declare class Collection {
232
243
  /**
233
244
  * Sets the Collection's annotation-level human-readable `name`, preserving
234
245
  * any existing `tags`. Convenience over `setMeta()`. The write is pinned to
235
- * the `etag` the `meta()` read returned (when the backend supports
236
- * `conditional-writes`) and rebases on a lost race, so a concurrent write --
237
- * an annotation write or a configuration change, which share the one
238
- * validator -- is re-read and re-applied rather than silently erased by this
239
- * 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.
240
250
  *
241
251
  * On an encrypted collection this is the collection's client-encrypted name
242
252
  * surface: the codec seals it into the `custom` envelope, and by convention
@@ -268,8 +278,8 @@ export declare class Collection {
268
278
  */
269
279
  get historyLogUrl(): string;
270
280
  /**
271
- * Reads the Collection's governing history log (the backend's
272
- * `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
273
283
  * `/meta/log` sub-resource, verbatim, together with its `ETag`. The log is
274
284
  * not a Resource of the Collection (absent from listings and the `changes`
275
285
  * feed) and not part of the `/meta` object; it is versioned by its own
@@ -412,8 +422,10 @@ export declare class Collection {
412
422
  * one page: `limit` caps its size (the server clamps its own maximum), and a
413
423
  * `hasMore` page carries the `cursor` to pass back for the next one.
414
424
  *
415
- * Requires the collection's backend to advertise the `blinded-index-query`
416
- * 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`).
417
429
  *
418
430
  * @param options {object}
419
431
  * @param [options.equals] {object | object[]} attribute/value pairs to match
@@ -451,8 +463,7 @@ export declare class Collection {
451
463
  *
452
464
  * On an encrypted collection a binary payload above the codec's
453
465
  * single-document threshold is auto-routed to the chunked-stream path, which
454
- * needs the backend's `chunked-streams` feature (`NotSupportedError` without
455
- * it, raised before anything is written).
466
+ * a server that does not serve the chunk endpoints answers with `501`.
456
467
  *
457
468
  * @param data {ResourceData}
458
469
  * @param options {object}
@@ -474,7 +485,7 @@ export declare class Collection {
474
485
  /**
475
486
  * Creates or replaces a resource by id (upsert). Forwards the
476
487
  * conditional-write options (`ifMatch` / `ifNoneMatch`) to `Resource.put`;
477
- * see it for the `conditional-writes` semantics. Returns the stored
488
+ * see it for the conditional-write semantics. Returns the stored
478
489
  * resource's new `etag`.
479
490
  *
480
491
  * @param resourceId {string}
@@ -537,11 +548,11 @@ export declare class Collection {
537
548
  * `limit` to its own maximum, so a short page can still be a full server
538
549
  * page.
539
550
  *
540
- * Requires the collection's backend to advertise the `changes-query` feature
541
- * (see `backend()`); a backend without it answers `501`. On an encrypted
542
- * collection the documents' `data` / `custom` are the scheme's opaque
543
- * envelopes (an EDV encrypted document under the v1 `edv` scheme) -- this
544
- * 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()`.
545
556
  *
546
557
  * Malformed responses fail the call with a `WasServerError` instead of
547
558
  * passing through as a page: a 2xx response with no JSON body
@@ -578,9 +589,10 @@ export declare class Collection {
578
589
  * `list()`. Unlike `list()`, a 404 on a later page throws: the collection
579
590
  * vanished mid-walk, and the pages already read are not a snapshot of
580
591
  * anything. The server faults `changes()` rejects on (a bodiless 2xx, a
581
- * live entry with no `data`, or a `501` from a backend without the
582
- * `changes-query` feature) fail the walk with the same `WasServerError`, as
583
- * 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.
584
596
  *
585
597
  * @param [options] {object}
586
598
  * @param [options.limit] {number} max documents per request (default 1000, the teaching server's maximum); the server reduces it to its own maximum
@@ -649,12 +661,11 @@ export declare class Collection {
649
661
  * you (404 conflation caveat). A server without backend support surfaces its
650
662
  * 501 as `NotImplementedError`.
651
663
  *
652
- * The descriptor's optional `features` array advertises optional server
653
- * affordances (e.g. `conditional-writes`, `blinded-index-query`,
654
- * `chunked-streams`); an absent token means the backend makes no claim to it,
655
- * so treat it as unsupported rather than assuming a default. (Client-side
656
- * encryption is not a backend feature -- it is a per-collection client concern
657
- * 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.)
658
669
  *
659
670
  * @returns {Promise<BackendDescriptor | null>}
660
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
@@ -143,16 +131,16 @@ export class Collection {
143
131
  }
144
132
  /**
145
133
  * The signed-request context handed to a codec that drives its own I/O (the
146
- * EDV codec reading a chunked blob back), bound to this handle's capability
147
- * and sharing its memoized feature probe.
134
+ * EDV codec reading a chunked blob back), bound to this handle's capability.
135
+ *
136
+ * Public so a sync replica can pass it to `DocCipher.decrypt`, which then
137
+ * reassembles a chunked envelope from its chunk resources on this
138
+ * collection. Building it performs no I/O.
148
139
  *
149
140
  * @returns {CodecRequestContext}
150
141
  */
151
- #codecContext() {
152
- return codecRequestContext(this.#context, {
153
- features: this.#features,
154
- capability: this.#capability
155
- });
142
+ codecContext() {
143
+ return codecRequestContext(this.#context, { capability: this.#capability });
156
144
  }
157
145
  /**
158
146
  * Resolves (once, then caches) the codec for this collection's reads and
@@ -294,17 +282,7 @@ export class Collection {
294
282
  * compare-and-swap attempt limit. One validator covers configuration and
295
283
  * annotations alike, so a configuration change now legitimately invalidates
296
284
  * an in-flight annotation write; rebasing is the normal outcome, not an
297
- * error. A backend without `conditional-writes` serves no validator, and
298
- * the write stays the unconditional upsert it has always been.
299
- *
300
- * Limitation, on a backend without `conditional-writes` only: the body
301
- * re-sends the stored `encryption` descriptor, and with no validator to pin
302
- * the `PUT` to, a descriptor rotation landing between the compose read and
303
- * the write is re-sent as the older roster -- refused as a spurious
304
- * `invalid-request-body` ("epochs is append-only") by a server enforcing the
305
- * descriptor invariants, and rolled back by one that does not. There is no
306
- * client-side remedy without a validator or a partial-update form, neither of
307
- * which WAS v0.5 offers (WCL-99).
285
+ * error.
308
286
  *
309
287
  * The absent-object rule is the masked-404 fail-closed policy at write level:
310
288
  * a `null` read means "missing OR not visible to you", and composing against
@@ -322,8 +300,7 @@ export class Collection {
322
300
  * @param [options.current] {object} an object the caller has already read,
323
301
  * used as the first attempt's baseline instead of re-reading it: the write
324
302
  * composes against it and pins to its validator, and a rebase re-reads. A
325
- * baseline carrying no validator makes the first attempt unconditional,
326
- * which is what a backend without `conditional-writes` offers anyway
303
+ * baseline carrying no validator is refused by the compare-and-swap loop
327
304
  * @param [options.allowAbsent] {boolean} compose against nothing (an
328
305
  * upsert) instead of throwing `NotFoundError` when the object cannot be
329
306
  * read
@@ -699,7 +676,7 @@ export class Collection {
699
676
  * no keys for, which is why {@link describe} -- the configuration read -- goes
700
677
  * without it.
701
678
  *
702
- * Against a backend with the `conditional-writes` feature the result also
679
+ * The result also
703
680
  * carries the object's current `etag` (its `metaVersion` validator) -- pass it
704
681
  * as `setMeta(meta, { ifMatch })` for a lost-update-safe update. One
705
682
  * validator covers the whole object: a configuration write and an annotation
@@ -747,8 +724,8 @@ export class Collection {
747
724
  * and encrypted collections alike. The key epoch the codec stamps the
748
725
  * envelope with travels as a top-level `epoch` member of the same body.
749
726
  *
750
- * Conditional writes (the backend's `conditional-writes` feature): pass
751
- * `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
752
729
  * update-if-unchanged, and a failed precondition throws
753
730
  * `PreconditionFailedError` (412). Without one the write is pinned to the
754
731
  * version it composed the configuration from and rebases on a lost race.
@@ -823,11 +800,10 @@ export class Collection {
823
800
  /**
824
801
  * Sets the Collection's annotation-level human-readable `name`, preserving
825
802
  * any existing `tags`. Convenience over `setMeta()`. The write is pinned to
826
- * the `etag` the `meta()` read returned (when the backend supports
827
- * `conditional-writes`) and rebases on a lost race, so a concurrent write --
828
- * an annotation write or a configuration change, which share the one
829
- * validator -- is re-read and re-applied rather than silently erased by this
830
- * 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.
831
807
  *
832
808
  * On an encrypted collection this is the collection's client-encrypted name
833
809
  * surface: the codec seals it into the `custom` envelope, and by convention
@@ -868,8 +844,8 @@ export class Collection {
868
844
  return toUrl({ serverUrl: this.#context.serverUrl, path: this.#logPath });
869
845
  }
870
846
  /**
871
- * Reads the Collection's governing history log (the backend's
872
- * `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
873
849
  * `/meta/log` sub-resource, verbatim, together with its `ETag`. The log is
874
850
  * not a Resource of the Collection (absent from listings and the `changes`
875
851
  * feed) and not part of the `/meta` object; it is versioned by its own
@@ -1128,8 +1104,10 @@ export class Collection {
1128
1104
  * one page: `limit` caps its size (the server clamps its own maximum), and a
1129
1105
  * `hasMore` page carries the `cursor` to pass back for the next one.
1130
1106
  *
1131
- * Requires the collection's backend to advertise the `blinded-index-query`
1132
- * 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`).
1133
1111
  *
1134
1112
  * @param options {object}
1135
1113
  * @param [options.equals] {object | object[]} attribute/value pairs to match
@@ -1149,9 +1127,8 @@ export class Collection {
1149
1127
  method: 'POST',
1150
1128
  capability: this.#capability,
1151
1129
  // The profile is bound here the way `changes()` binds its own: same
1152
- // endpoint, no client-side feature probe -- a backend that does not
1153
- // implement the profile answers 501, which is a clearer signal than a
1154
- // guess made from the backend descriptor.
1130
+ // endpoint, no client-side gate -- a server that does not implement the
1131
+ // profile answers 501.
1155
1132
  json: {
1156
1133
  profile: 'blinded-index',
1157
1134
  ...query,
@@ -1171,7 +1148,7 @@ export class Collection {
1171
1148
  // Each envelope is an independent JWE open with nothing carried between
1172
1149
  // them, so the page decrypts concurrently. `Promise.all` preserves order,
1173
1150
  // so `items` still matches the server's ranking.
1174
- const codecContext = this.#codecContext();
1151
+ const codecContext = this.codecContext();
1175
1152
  const items = await Promise.all(documents.map(async (envelope) => {
1176
1153
  // Restrict-mode ids make the stored document's own id the WAS resource
1177
1154
  // id, so it is also the id the codec verifies the envelope's
@@ -1211,9 +1188,6 @@ export class Collection {
1211
1188
  collectionId: this.id,
1212
1189
  resourceId,
1213
1190
  capability: options.capability ?? this.#capability,
1214
- // Share this collection's memoized feature probe so per-resource handles
1215
- // do not each repeat the backend-descriptor round-trip.
1216
- features: this.#features,
1217
1191
  // A per-resource encryption override resolves its own codec (honoring the
1218
1192
  // override); without one, share this collection's resolved codec so the
1219
1193
  // resource handle does not repeat the descriptor-discovery round-trip.
@@ -1231,8 +1205,7 @@ export class Collection {
1231
1205
  *
1232
1206
  * On an encrypted collection a binary payload above the codec's
1233
1207
  * single-document threshold is auto-routed to the chunked-stream path, which
1234
- * needs the backend's `chunked-streams` feature (`NotSupportedError` without
1235
- * it, raised before anything is written).
1208
+ * a server that does not serve the chunk endpoints answers with `501`.
1236
1209
  *
1237
1210
  * @param data {ResourceData}
1238
1211
  * @param options {object}
@@ -1247,7 +1220,6 @@ export class Collection {
1247
1220
  pathForId: mintedId => resourcePath(this.spaceId, this.id, mintedId),
1248
1221
  codec,
1249
1222
  data,
1250
- features: this.#features,
1251
1223
  contentType: options.contentType,
1252
1224
  capability: this.#capability
1253
1225
  });
@@ -1315,7 +1287,7 @@ export class Collection {
1315
1287
  /**
1316
1288
  * Creates or replaces a resource by id (upsert). Forwards the
1317
1289
  * conditional-write options (`ifMatch` / `ifNoneMatch`) to `Resource.put`;
1318
- * see it for the `conditional-writes` semantics. Returns the stored
1290
+ * see it for the conditional-write semantics. Returns the stored
1319
1291
  * resource's new `etag`.
1320
1292
  *
1321
1293
  * @param resourceId {string}
@@ -1396,11 +1368,11 @@ export class Collection {
1396
1368
  * `limit` to its own maximum, so a short page can still be a full server
1397
1369
  * page.
1398
1370
  *
1399
- * Requires the collection's backend to advertise the `changes-query` feature
1400
- * (see `backend()`); a backend without it answers `501`. On an encrypted
1401
- * collection the documents' `data` / `custom` are the scheme's opaque
1402
- * envelopes (an EDV encrypted document under the v1 `edv` scheme) -- this
1403
- * 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()`.
1404
1376
  *
1405
1377
  * Malformed responses fail the call with a `WasServerError` instead of
1406
1378
  * passing through as a page: a 2xx response with no JSON body
@@ -1478,9 +1450,10 @@ export class Collection {
1478
1450
  * `list()`. Unlike `list()`, a 404 on a later page throws: the collection
1479
1451
  * vanished mid-walk, and the pages already read are not a snapshot of
1480
1452
  * anything. The server faults `changes()` rejects on (a bodiless 2xx, a
1481
- * live entry with no `data`, or a `501` from a backend without the
1482
- * `changes-query` feature) fail the walk with the same `WasServerError`, as
1483
- * 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.
1484
1457
  *
1485
1458
  * @param [options] {object}
1486
1459
  * @param [options.limit] {number} max documents per request (default 1000, the teaching server's maximum); the server reduces it to its own maximum
@@ -1622,12 +1595,11 @@ export class Collection {
1622
1595
  * you (404 conflation caveat). A server without backend support surfaces its
1623
1596
  * 501 as `NotImplementedError`.
1624
1597
  *
1625
- * The descriptor's optional `features` array advertises optional server
1626
- * affordances (e.g. `conditional-writes`, `blinded-index-query`,
1627
- * `chunked-streams`); an absent token means the backend makes no claim to it,
1628
- * so treat it as unsupported rather than assuming a default. (Client-side
1629
- * encryption is not a backend feature -- it is a per-collection client concern
1630
- * 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.)
1631
1603
  *
1632
1604
  * @returns {Promise<BackendDescriptor | null>}
1633
1605
  */