@cloudbitmaps/roaring 0.22.0 → 0.24.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/dist/index.d.ts CHANGED
@@ -25,9 +25,36 @@
25
25
  */
26
26
  import type { BudgetOption, GenerationEntry, GenerationMetadata, LoadGuard, LoadInput, LoadOptions, LoadRefusal, LoadResult, RollbackResult, Clock, Entropy, ConsistencyReport, DropResult, ExportManifest, ExportOptions, ExportSink, IAuditSink, IMetricsSink, RetentionPolicy, RetireExpiredOptions, RetireExpiredResult, RetryPolicy, Rng, SetRetentionResult, PinnedAt, SegmentRef } from '@cloudbitmaps/core';
27
27
  import type { IKeystore, IStorageDriver, StorageBackend, StorageChunkSource } from '@cloudbitmaps/core/driver-kit';
28
+ import type { DestroyResult, EraseDeps } from '@cloudbitmaps/core';
28
29
  import type { SegmentInfo } from '@cloudbitmaps/core';
30
+ import type { PreflightResult } from '@cloudbitmaps/core';
29
31
  import type { Expr, MaterializeManyFeedRecord, MaterializeManyStats } from '@cloudbitmaps/core';
30
32
  import { deserializePortable } from './roaring-codec.js';
33
+ /**
34
+ * Crypto-shred one segment. It cannot be undone through the library (a registry restore to a point before it can).
35
+ * `confirmSegment` must equal `ref.segment` (a guard against an accidental destroy). A non-encrypted segment is
36
+ * rejected unless you opt in via `allowCleartext`: it has no key to shred, its Storage bytes stay readable, and the
37
+ * call emits a `segment.tombstone` audit event instead of `segment.erase`. A write that gets no answer is settled by
38
+ * reading the row back, waiting between reads on `deps.clock` (the system clock by default).
39
+ */
40
+ export declare function destroySegment(ref: SegmentRef, deps: EraseDeps, options: {
41
+ confirmSegment: string;
42
+ allowCleartext?: boolean;
43
+ audit?: IAuditSink;
44
+ }): Promise<DestroyResult>;
45
+ /**
46
+ * Crypto-shred every segment in a namespace. It cannot be undone through the library. `confirmNamespace` must equal
47
+ * `namespace`. Returns a per-segment result, in the order the registry listed the segments, which is unspecified. A
48
+ * write that gets no answer is settled as {@link destroySegment}'s is.
49
+ */
50
+ export declare function eraseNamespace(namespace: string, deps: EraseDeps, options: {
51
+ confirmNamespace: string;
52
+ allowCleartext?: boolean;
53
+ audit?: IAuditSink;
54
+ maxScanSegments?: number;
55
+ }): Promise<{
56
+ destroyed: DestroyResult[];
57
+ }>;
31
58
  /**
32
59
  * Wiring for a {@link CloudRoaring} store. **Only `storage` is required** — the minimal call is
33
60
  * `new CloudRoaring({ storage: backend })`. A backend resolves generations with one strong read, reads
@@ -76,7 +103,8 @@ export interface CloudRoaringOptions {
76
103
  * attempt, capped at 2 s, with full jitter): `has`, `count`,
77
104
  * `iterate` and the combines, the `*Into` verbs' reads of their operands included, a pinned handle's reads and
78
105
  * `pin()` itself, and the reads a write makes along the way: a load's guard read of the current generation, and an
79
- * erasure's reads of the generation it rewrites, of the one it wrote and of any other that may still hold the id.
106
+ * erasure's reads of the generation it rewrites, of the one it wrote and of any other that may still hold the id, and
107
+ * the search `subjectReport` and `eraseSubject` make under a destroyed segment (its listing of the bucket included).
80
108
  * This option does not govern writes, nor the calls that read the registry or list the bucket directly (`exists`,
81
109
  * `segments`, `generations`, `getRetention`, and the registry scan `subjectReport`, `exportSegments` and
82
110
  * `checkConsistency` start from): they report a transient fault to their caller, because a conditional write that
@@ -114,9 +142,12 @@ export interface CloudRoaringOptions {
114
142
  }
115
143
  /** {@link CloudRoaringOptions.cache} — the memory and staleness bounds. */
116
144
  export interface CacheOptions {
117
- /** Ceiling on decoded Storage chunks held in RAM (default 1024). */
145
+ /** Ceiling on decoded Storage chunks held in RAM (default 1024): an integer of at least 1, else `ValidationError`. */
118
146
  readonly maxChunks?: number;
119
- /** Optional TTL on cached chunks (ms). Omit to keep a chunk until it is evicted by the count bound. */
147
+ /**
148
+ * Optional TTL on cached chunks (ms): a finite number above 0, else `ValidationError`. Omit to keep a chunk until it is
149
+ * evicted by the count bound.
150
+ */
120
151
  readonly ttlMs?: number;
121
152
  /**
122
153
  * How long (ms) the store trusts a segment's resolved `currentGen` before re-resolving it on the next read
@@ -144,7 +175,8 @@ export interface CacheOptions {
144
175
  readonly genTtlMs?: number;
145
176
  /**
146
177
  * Ceiling on how many segments' `.crbm` readers (each holding a parsed index) the store keeps open at once
147
- * (default 1024) — the steady-state memory bound for a long-running server that reads across many segments.
178
+ * (default 1024; an integer of at least 1, else `ValidationError`) — the steady-state memory bound for a long-running
179
+ * server that reads across many segments.
148
180
  * Past it the least-recently-used segment's reader is evicted; re-opening it later is one cheap tail GET. With a
149
181
  * timed refresh ({@link CacheOptions.genTtlMs} above 0, and a backend) the store also keeps up to 8 times this many
150
182
  * segments' resolutions (what it read of each segment's row: never an unwrapped key, though the wrapped keys are in
@@ -167,7 +199,7 @@ export interface CacheOptions {
167
199
  * heap (e.g. a 128 MB Lambda); this evicts the least-recently-used reader once the summed weight
168
200
  * would exceed the ceiling — whichever of the count/byte bounds binds first. A sixteenth of it (4 MiB by default)
169
201
  * bounds the segments' resolutions a store with a timed refresh keeps besides. Lower it for memory-tight
170
- * deployments that read across wide segments. A ceiling below two readers' weight (about 7.7 KB for tiny ones) keeps one reader open at a time. Applies whenever the store builds its own read path.
202
+ * deployments that read across wide segments. An integer of at least 1, else `ValidationError`. A ceiling below two readers' weight (about 7.7 KB for tiny ones) keeps one reader open at a time. Applies whenever the store builds its own read path.
171
203
  */
172
204
  readonly readerMaxBytes?: number;
173
205
  }
@@ -181,11 +213,13 @@ export interface EncryptionOptions {
181
213
  readonly keystore?: IKeystore;
182
214
  /**
183
215
  * Refuse to touch a **cleartext** segment — a guard against silently reading, or writing, data that should be
184
- * encrypted. Needs a backend, for the same reason as {@link EncryptionOptions.keystore}. Off by default.
216
+ * encrypted. Needs a backend, for the same reason as {@link EncryptionOptions.keystore}. Off by default. Exactly a
217
+ * boolean: any other value, a truthy string included, throws `ValidationError`.
185
218
  *
186
219
  * It refuses **writes** as well as reads, which is easy to miss: the `*Into` verbs and `eraseSubject` both
187
220
  * carry it into their write path, so on a cleartext segment a materialisation throws and an erasure records
188
- * `note: 'error: requireEncryption: …'` in its ledger rather than erasing. And since a segment's encryption is
221
+ * `note: 'error: KeyUnavailableError: requireEncryption: …'` in its ledger rather than erasing, whatever id it erases and
222
+ * whether or not the id is in the segment: it does not read the segment. And since a segment's encryption is
189
223
  * decided at its **first** generation, this cannot be switched on for a segment that already has one — load
190
224
  * into a new encrypted segment and drop the old one.
191
225
  */
@@ -229,24 +263,39 @@ export interface SeamOptions {
229
263
  * passed here is refused with {@link ValidationError}.
230
264
  */
231
265
  export interface SegmentOptions {
266
+ /** The segment's namespace, or `undefined` for the default one. */
232
267
  readonly namespace?: string;
233
268
  }
234
269
  /** A segment reference in a subject report / erasure ledger. */
235
270
  export interface SubjectSegmentRef {
271
+ /** The segment's name. */
236
272
  readonly segment: string;
273
+ /** The segment's namespace, or `undefined` for the default one. */
237
274
  readonly namespace?: string;
238
275
  }
239
- /** Result of {@link CloudRoaring.subjectReport} — the segments an id is a member of (over registered segments). */
276
+ /** Result of {@link CloudRoaring.subjectReport}: the segments an id is a member of, and the destroyed segments whose leftover objects hold it. */
240
277
  export interface SubjectReport {
278
+ /** The id the report is about. */
241
279
  readonly id: number;
242
280
  /** The registered segments the id is currently a member of. */
243
281
  readonly segments: SubjectSegmentRef[];
282
+ /**
283
+ * The destroyed segments whose leftover objects still hold the id in the clear: one destroyed with `allowCleartext`,
284
+ * dropped while a load wrote an object its sweep did not catch, or crypto-shredded over an object a cleartext writer
285
+ * left. No read resolves them, so the id is a member of none, but its bytes are in the bucket, and `eraseSubject`
286
+ * deletes them. A crypto-shredded segment's own objects are sealed under a key no row holds and are never a holder,
287
+ * so it is listed only when an object left under it in the clear holds the id. A destroyed segment with no
288
+ * object left is not listed either. `[]` when none.
289
+ */
290
+ readonly tombstones: SubjectSegmentRef[];
244
291
  /** How many registered segments were scanned (the completeness denominator). */
245
292
  readonly scannedSegments: number;
246
293
  }
247
294
  /** One segment's entry in an erasure ledger (see {@link EraseSubjectResult}). */
248
295
  export interface SubjectErasureEntry {
296
+ /** The segment's name. */
249
297
  readonly segment: string;
298
+ /** The segment's namespace, or `undefined` for the default one. */
250
299
  readonly namespace?: string;
251
300
  /**
252
301
  * True iff the id **was** in the segment and **no generation of it holds the id now** — not the current one, not
@@ -269,15 +318,15 @@ export interface SubjectErasureEntry {
269
318
  * no pointer (a purge and re-creation, or a hand-made write), while the call was in flight, so **this call** did
270
319
  * not erase the id;
271
320
  * re-run against the new generation, which erases it if it is still there and reports nothing for the segment
272
- * if the racing writer already removed it. `` `error: <message>` `` — an isolated per-segment fault
321
+ * if the racing writer already removed it. `` `error: <class>: <message>` `` — an isolated per-segment fault, named by its error's class
273
322
  * (per-segment faults are recorded so one segment can't discard the whole ledger); re-run after fixing the
274
323
  * fault. A budget refusal is one of these: the segment's generations did not fit `budget`, so it was not finished;
275
324
  * re-run with a higher `budget`. A fault that landed once part of the work was already done — a Storage `delete` fault, a collect that
276
325
  * could not prove the segment was still the same one, or a generation still holding the id when the bucket was
277
326
  * listed at the end, whether or not a rewrite was published first — also re-runs, but **read what the re-run
278
327
  * says**: it usually reports `erased: true` against the generation it found the id in, it reports
279
- * nothing at all if a racing collector took that generation first (the bit is gone, but no run holds a
280
- * receipt for it), and if the segment's row has since been purged it is no longer scanned at all — anything
328
+ * nothing at all if a racing collector took that generation first, or this call's own delete of it landed after a
329
+ * fault the call could not settle (the bit is gone, but no run holds a receipt for it), and if the segment's row has since been purged it is no longer scanned at all — anything
281
330
  * left in its bucket is an orphan, which `store.generations(ref)` lists and `store.dropSegment(ref, {
282
331
  * confirmSegment })` deletes; `checkConsistency` and the collection a load runs read rows, so neither reaches it.
283
332
  * **Segments the id is not in
@@ -291,6 +340,7 @@ export interface SubjectErasureEntry {
291
340
  * return value only (no library-side persistence): persist it / route it to your audit sink as you see fit.
292
341
  */
293
342
  export interface EraseSubjectResult {
343
+ /** The id that was erased. */
294
344
  readonly id: number;
295
345
  /** Per-segment records for the segments the id was found in (absent segments are not listed). */
296
346
  readonly erasedFrom: SubjectErasureEntry[];
@@ -413,6 +463,10 @@ export type MaterializeManyOutcome = MaterializeResult | {
413
463
  export interface MaterializeManyRun {
414
464
  /** One per output, in the order given: one output's refusal or error never stops another. */
415
465
  readonly outputs: MaterializeManyOutcome[];
466
+ /**
467
+ * What the call did: the groups it ran, its requests by class, its budget and memory, and the figures of each operand
468
+ * and output.
469
+ */
416
470
  readonly stats: MaterializeManyStats;
417
471
  }
418
472
  /**
@@ -420,6 +474,7 @@ export interface MaterializeManyRun {
420
474
  * judged against its `dest` as its publish would be, and nothing is written. See {@link CloudRoaring.materializeMany}.
421
475
  */
422
476
  export interface MaterializeManyDryRunOptions extends MaterializeManyOptions {
477
+ /** `true` makes the call a dry run: every output is computed and judged, and nothing is written. */
423
478
  readonly dryRun: true;
424
479
  }
425
480
  /**
@@ -428,7 +483,9 @@ export interface MaterializeManyDryRunOptions extends MaterializeManyOptions {
428
483
  * run for a publish.
429
484
  */
430
485
  export interface MaterializeDryRunResult {
486
+ /** Always `true`: the output was computed and judged, not published. */
431
487
  readonly dryRun: true;
488
+ /** Always `false`: nothing was written. */
432
489
  readonly published: false;
433
490
  /** Distinct ids the output would hold. */
434
491
  readonly cardinality: number;
@@ -449,6 +506,10 @@ export type MaterializeManyDryRunOutcome = MaterializeDryRunResult | {
449
506
  export interface MaterializeManyDryRun {
450
507
  /** One per output, in the order given. */
451
508
  readonly outputs: MaterializeManyDryRunOutcome[];
509
+ /**
510
+ * What the dry run did: the groups it ran, its requests by class, its budget and memory, and the figures of each
511
+ * operand and output.
512
+ */
452
513
  readonly stats: MaterializeManyStats;
453
514
  }
454
515
  /** What an `*Into` verb wrote: the new generation of the destination, and whether it became current. */
@@ -512,6 +573,7 @@ export declare class CloudRoaring {
512
573
  private readonly metrics;
513
574
  private readonly storageDriver;
514
575
  private readonly registry;
576
+ private readonly backend;
515
577
  private readonly keystore;
516
578
  private readonly requireEncryption;
517
579
  /** Resolved store-level per-op budget (null = disabled); the admin scans use it, with a per-op override. */
@@ -535,6 +597,19 @@ export declare class CloudRoaring {
535
597
  * no `next` or a keystore with no `createDek` builds a store that throws a raw `TypeError` at its first load or read.
536
598
  */
537
599
  private static rejectHollowSeams;
600
+ /**
601
+ * Refuse a `cache` or `encryption` value that can never be honoured, by the name the caller wrote. The sizes reach
602
+ * the caches under their own internal names, so left to them an error would name `maxEntries` or `maxBytes`; and
603
+ * `encryption.required` must be exactly a boolean, since the read path took a truthy string for `true` while every
604
+ * write path did not, which refused cleartext reads and still wrote cleartext.
605
+ */
606
+ private static rejectBadValues;
607
+ /**
608
+ * Builds a store. Only `storage` is required: pass a backend such as `S3Storage` or `MemoryStorage`. `cache`,
609
+ * `encryption`, `retry`, `metrics`, `budget` and `seams` tune it. An option it does not take, a `cache` size or `ttlMs`
610
+ * that is not a usable number, an `encryption.required` that is not a boolean, or a seam missing a method the store
611
+ * calls, throws `ValidationError`.
612
+ */
538
613
  constructor(options: CloudRoaringOptions);
539
614
  /**
540
615
  * The write-side deps, from the store's own drivers, for the lifecycle helpers and the `*Into` verbs. Requires
@@ -743,21 +818,50 @@ export declare class CloudRoaring {
743
818
  * tax every load for a rare request; this admin scan is `O(registered segments)` and touches no hot path. Needs
744
819
  * a storage backend (throws {@link UnsupportedError} otherwise).
745
820
  *
821
+ * **Scope: one `namespace`, or `{ allNamespaces: true }`, never both** (both throws `ValidationError`, as does
822
+ * neither). A segment loaded with no `namespace` is in no namespace you can name: only `{ allNamespaces: true }`
823
+ * reaches it. `'_default'`, the label the export tool and the disaster-recovery samples print, and the bucket's
824
+ * object keys use, for such a segment, is an ordinary namespace name here, and passing it scans a namespace of that name, not those segments.
825
+ *
746
826
  * **Current as of the registry row, not as of the reader's cache.** Each segment's resolved generation is
747
827
  * compared with the row the scan listed, and a segment whose cached generation differs is re-resolved before the
748
828
  * read, so a load or an erasure from another process shows at once — whatever `cache.genTtlMs` is, `0` included.
749
829
  * The comparison is on the generation **and** the row's token, so a segment retired, purged and loaded again from
750
830
  * generation 0 while this store held its old generation 0 is told apart too.
751
- */
752
- subjectReport(id: number, options?: {
753
- namespace?: string;
754
- allNamespaces?: boolean;
831
+ *
832
+ * **A destroyed segment is searched as {@link CloudRoaring.eraseSubject} searches it.** No read resolves a
833
+ * tombstone, so the id is a member of none, but a cleartext `destroySegment` (`allowCleartext`), or a `dropSegment`
834
+ * whose sweep missed an object a load was still writing, leaves objects anyone with bucket access can read. Each
835
+ * object left under the tombstone is opened newest first until one holds the id, and the segment is then listed in
836
+ * `tombstones`, never in `segments`. A crypto-shredded segment's own objects are sealed under a key no row holds and are
837
+ * never a holder: it is listed only when an object left under it in the clear holds the id. The cost is one listing per destroyed segment in scope (1 request when nothing is left), and for each
838
+ * object opened a tail read and, where its index lists the id's chunk, a chunk read (two tail reads for an encrypted
839
+ * object, which never holds the id): 7 requests for a cleartext destroy with 3 objects, 21 for 10. The budget is
840
+ * charged one unit for each object opened past the one the row names, as `eraseSubject` charges. A report that runs
841
+ * out, or whose listing or read fails after the store's retry, rejects rather than under-reporting, so one leftover
842
+ * object that cannot be opened makes every report over its scope reject until it is removed (`generations(ref)` lists
843
+ * what is left, `dropSegment` deletes it). A report refused for budget while it searches a destroyed segment reports
844
+ * `spent` as `limit + 1`, a lower bound.
845
+ */
846
+ subjectReport(id: number, options: {
755
847
  concurrency?: number;
756
848
  budget?: BudgetOption;
757
- }): Promise<SubjectReport>;
849
+ } & ({
850
+ namespace: string;
851
+ allNamespaces?: false;
852
+ } | {
853
+ allNamespaces: true;
854
+ namespace?: undefined;
855
+ })): Promise<SubjectReport>;
758
856
  /**
759
857
  * **Subject erasure (GDPR Art. 17): remove an id from every segment it's in, with the bit physically gone
760
- * from the bucket on return.**
858
+ * from the bucket on return for each segment the ledger reports `erased: true`.** A noncurrent version, a replica
859
+ * or a backup keeps the old object until its own lifecycle removes it.
860
+ *
861
+ * **Scope: one `namespace`, or `{ allNamespaces: true }`, never both** (both throws `ValidationError`, as does
862
+ * neither). A segment loaded with no `namespace` is in no namespace you can name: only `{ allNamespaces: true }`
863
+ * reaches it. `'_default'`, the label the export tool and the disaster-recovery samples print, and the bucket's
864
+ * object keys use, for such a segment, is an ordinary namespace name here, and passing it scans a namespace of that name, not those segments.
761
865
  *
762
866
  * For each **registered** segment the id is a member of, `eraseIdFromSegment` rewrites the current generation
763
867
  * without the id — every chunk streamed through, one bit cleared — publishes the rewrite **fenced on the
@@ -822,21 +926,27 @@ export declare class CloudRoaring {
822
926
  * `O(registered segments + superseded generations)`, no hot-path cost: a segment whose current generation lacks
823
927
  * the id is searched generation by generation, one open for each other generation in its bucket, and with the
824
928
  * keep-everything default of the `*Into` verbs that is one per generation the segment ever had. The per-op
825
- * `budget` is charged one unit for each segment and one for each generation opened beyond the one its row names,
826
- * so a fleet with long histories can exhaust it where the segment count alone would not. A segment that does is
929
+ * `budget` is charged one unit for each segment and one for each generation opened beyond the one its row names, so
930
+ * a fleet with long histories can exhaust it where the segment count alone would not. A generation is charged at its
931
+ * first open only: a later open of it in the call, a retry of a failed read included, costs no more units. A segment
932
+ * that exhausts the budget is
827
933
  * reported `erased: false` with an `error:` note, before it deletes anything (the one refusal that can come after a
828
934
  * rewrite is the last check for a generation a concurrent writer left behind), and the
829
935
  * rest of the scan continues: the call itself does not throw for it. Per-subject crypto-shred is infeasible (a subject's bit is
830
936
  * co-mingled in a shared container), so this is the single-subject erasure route; whole-segment/tenant erasure
831
937
  * is `dropSegment` / the `destroySegment`/`eraseNamespace` free functions.
832
938
  */
833
- eraseSubject(id: number, options?: {
834
- namespace?: string;
835
- allNamespaces?: boolean;
939
+ eraseSubject(id: number, options: {
836
940
  audit?: IAuditSink;
837
941
  concurrency?: number;
838
942
  budget?: BudgetOption;
839
- }): Promise<EraseSubjectResult>;
943
+ } & ({
944
+ namespace: string;
945
+ allNamespaces?: false;
946
+ } | {
947
+ allNamespaces: true;
948
+ namespace?: undefined;
949
+ })): Promise<EraseSubjectResult>;
840
950
  private eraseSubjectRun;
841
951
  /**
842
952
  * Every generation still in the bucket for this segment, ascending, with the current one marked.
@@ -846,6 +956,7 @@ export declare class CloudRoaring {
846
956
  * choose from, which is the reason to look at it. One registry read and one listing; it does not open the objects.
847
957
  * Each entry says whether the row knows the generation (`known`): a known generation needs no `allowUnknown`; an unknown
848
958
  * one does, except below a row's pointer when the row has no usable record or the target is older than a full one reaches.
959
+ * No entry is `current` on a destroyed segment: its row keeps the pointer it had, but no read resolves through it.
849
960
  *
850
961
  * Needs a backend.
851
962
  */
@@ -925,8 +1036,9 @@ export declare class CloudRoaring {
925
1036
  * {@link ValidationError} before any request to storage, and a known one whose object carries another checksum than
926
1037
  * the recorded one throws {@link IntegrityError}, with or without a keystore, since the footer is in the clear. A
927
1038
  * generation not in the bucket (collected, or never written) throws `NotFoundError` naming what *is* available, a
928
- * crypto-shredded segment throws {@link ValidationError} because every generation of it is unreadable, and a target
929
- * that is cleartext under an encrypted segment, or encrypted under a cleartext one, throws {@link IntegrityError} from
1039
+ * destroyed segment (crypto-shredded, destroyed in the clear or dropped) throws {@link ValidationError}, because no
1040
+ * generation resolves through a destroyed row, and a target that is cleartext under an encrypted segment, or
1041
+ * encrypted under a cleartext one, throws {@link IntegrityError} from
930
1042
  * one tail read of it, because every read would refuse it. Rolling to the generation already current is a no-op that
931
1043
  * reports itself, once one footer read finds its object in the bucket (and the one the row recorded); when the object is
932
1044
  * gone it throws `NotFoundError` naming what is.
@@ -937,8 +1049,10 @@ export declare class CloudRoaring {
937
1049
  * key (it holds none of the key's KEKs, one it holds does not unwrap it, or it throws `TransientError` or times out
938
1050
  * as `AbortSignal.timeout()` and the AWS SDK report a timeout), a rollback onto a known generation still happens,
939
1051
  * opening nothing, and the row carries no summary of the target. Any other failure of the keystore is
940
- * thrown. A swap of the pointer that gets no answer is settled by reading the row: one that landed, the row being the
941
- * one the swap leaves, is checked as any is, and otherwise its `TransientError` is thrown. After the swap the target's
1052
+ * thrown. A swap of the pointer that gets no answer, or that meets a conflict, is settled by reading the row: one
1053
+ * that landed, the row's pointer being at the target over a write this call sent (the write token, on a registry that
1054
+ * reports them), is checked as any is, and otherwise its `TransientError` is thrown, or a `WriteConflictError` after
1055
+ * a conflict, with no move recorded. After the swap the target's
942
1056
  * footer is read once more, and the pointer put back if the object is gone or is another.
943
1057
  *
944
1058
  * It deletes nothing. The generations above the new pointer stay put — which is what makes this reversible —
@@ -977,9 +1091,16 @@ export declare class CloudRoaring {
977
1091
  * `input` is ids (any sync or async iterable of integers in `[0, 2^32)`), or a whole bitmap: `{ bitmap }`, anything
978
1092
  * with `serialize('portable')` such as `roaring`'s `RoaringBitmap32`, or `{ serialized }`, portable Roaring bytes.
979
1093
  * A bitmap is checked (size cap, structure, safe deserializer) before the first request, written from its own
980
- * containers with no per-id work, and gives the generation chunk for chunk what its ids would. A bare
981
- * `RoaringBitmap32` passed as ids loads as `{ bitmap }`. A `Uint8Array` or `Buffer` passed as ids is refused with
982
- * `ValidationError`, since each byte would load as an id: pass bytes as `{ serialized }`.
1094
+ * containers with no per-id work, and gives the generation chunk for chunk what its ids would. An
1095
+ * iterable with a `serialize` method (a `RoaringBitmap32`, another copy's bitmap, or a bitmap `deserializePortable`
1096
+ * returned) passed as ids loads as `{ bitmap }` and is not iterated. A `Uint8Array` or `Buffer` passed as ids is
1097
+ * refused with `ValidationError`, since each byte would load as an id, even when it has a `serialize` of its own:
1098
+ * pass bytes as `{ serialized }`.
1099
+ *
1100
+ * Ids are held whole in memory before the object is written: the generation's bitmaps and a buffer of up to about 28
1101
+ * MB. Ids that already ascend can be loaded with `sorted: true` instead, which writes them one chunk at a time while
1102
+ * the object uploads, so the load holds one chunk and the writer's index (up to about 7 MiB, about 8 MiB for an
1103
+ * encrypted segment, derived), whatever the segment's size, and writes the same object ({@link LoadOptions.sorted}).
983
1104
  *
984
1105
  * The whole write path in one call: take the next generation number, write the object, check the result is
985
1106
  * plausible, move the pointer, collect what the move superseded. Composed by hand those are four functions and
@@ -1038,7 +1159,14 @@ export declare class CloudRoaring {
1038
1159
  * does the first load of a row that records none, which then records it. {@link LoadResult.collected} then names
1039
1160
  * what the pass deleted by name, and one name may have been gone already.
1040
1161
  *
1041
- * What it **throws** for is a fault rather than an outcome: invalid options or ids, and a crypto-shredded
1162
+ * `input` cannot be a stream of this library (`iterate`, `everyNth`, `intersect`, `union`, `andNot`, as returned) that
1163
+ * read the segment being loaded, from this store or one built over the same registry driver: a load publishes over
1164
+ * whatever the segment is by then, so it would replace another writer's newer load with a result built from an older
1165
+ * one, and it throws {@link ValidationError}. Ids read from another store over another backend load as any ids do.
1166
+ * Two separate store instances over one bucket cannot be told apart, so this does not cover them; this release has no
1167
+ * fenced in-place update, so write the result into a new segment and point readers at it.
1168
+ *
1169
+ * What it **throws** for is a fault rather than an outcome: invalid options or ids, and a destroyed
1042
1170
  * segment (`ValidationError`); a key the keystore cannot provide (`KeyUnavailableError`); a current generation
1043
1171
  * that will not open when a guard has to read its size, which it does only when the row has no usable summary of it
1044
1172
  * (`IntegrityError`); a driver failure; and a fault in the collection's own reads, listing or deletes, or in the write
@@ -1062,11 +1190,14 @@ export declare class CloudRoaring {
1062
1190
  */
1063
1191
  load(ref: SegmentRef, input: LoadInput, options?: LoadOptions): Promise<LoadResult>;
1064
1192
  /**
1065
- * **Dispose of a segment — tombstone it, then delete its storage objects.** Irreversible.
1193
+ * **Dispose of a segment — tombstone it, then delete its storage objects.** It cannot be undone through the
1194
+ * library (a restore from the registry's and the bucket's versions or backups can).
1066
1195
  *
1067
- * The operation a rolling window needs: `destroySegment` crypto-shreds (bytes unreadable everywhere including
1068
- * backups, but still sitting in your bucket and still billed, and it requires encryption), while this one
1069
- * removes the storage and works on a cleartext segment. On an encrypted segment it does both.
1196
+ * The operation a rolling window needs: `destroySegment` crypto-shreds (it removes the key from the segment's
1197
+ * current registry row, so the bytes are unreadable everywhere, backups included, once no retained copy of the row
1198
+ * holds the key or every KEK that wrapped it is destroyed; the objects still sit in your bucket and are still
1199
+ * billed, and it requires encryption), while this one removes the storage and works on a cleartext segment. On an
1200
+ * encrypted segment it does both.
1070
1201
  *
1071
1202
  * Pass `{ dryRun: true }` first — it reports the generations it *would* delete and changes nothing. That
1072
1203
  * matters more than the `confirmSegment` guard for anything automated, because in a loop the guard is the same
@@ -1112,8 +1243,9 @@ export declare class CloudRoaring {
1112
1243
  audit?: IAuditSink;
1113
1244
  }): Promise<DropResult>;
1114
1245
  /**
1115
- * **Record when this segment becomes eligible for retirement.** One registry write; nothing is deleted here,
1116
- * and nothing starts running. `retireExpired` is what acts on the policy, and **you** decide when that runs —
1246
+ * **Record when this segment becomes eligible for retirement.** One policy write, plus a best-effort write of its
1247
+ * due-index pointer (and removal of the old pointer when the expiry day moves); no data is deleted here, and
1248
+ * nothing starts running. `retireExpired` is what acts on the policy, and **you** decide when that runs —
1117
1249
  * an EventBridge rule, a CronJob, a queue consumer, whatever your deployment already has. This library starts
1118
1250
  * no background thread (it has to work identically in a Lambda, an edge isolate and a long-lived server).
1119
1251
  *
@@ -1135,7 +1267,7 @@ export declare class CloudRoaring {
1135
1267
  * A value in the past is legal and means "eligible on the next sweep" — backfilling a policy onto existing
1136
1268
  * buckets is normal. A value below `1_000_000_000_000` (2001-09-09) is rejected: it is almost certainly epoch
1137
1269
  * **seconds**, which would read as long-expired and retire the segment on the next pass. Needs a storage
1138
- * backend (throws {@link UnsupportedError} otherwise), and refuses a crypto-shredded segment.
1270
+ * backend (throws {@link UnsupportedError} otherwise), and refuses a destroyed segment.
1139
1271
  */
1140
1272
  setRetention(ref: SegmentRef, policy: RetentionPolicy): Promise<SetRetentionResult>;
1141
1273
  /**
@@ -1146,8 +1278,10 @@ export declare class CloudRoaring {
1146
1278
  */
1147
1279
  getRetention(ref: SegmentRef): Promise<RetentionPolicy | null | 'invalid'>;
1148
1280
  /**
1149
- * **Cancel a segment's expiry** so no sweep retires it. Returns whether a policy was actually removed (`false`
1150
- * when there was none). A separate verb from `setRetention` on purpose: "never expire" as a magic value passed
1281
+ * **Cancel a segment's expiry** so no sweep retires it. Returns whether this call removed a policy (`false`
1282
+ * when there was none, and also when a write that got no answer cannot be shown to be this call's and the
1283
+ * row holds no expiry: the expiry is gone either way, and its due-index pointer is removed. A later write that set an
1284
+ * expiry is cleared too, and the answer is `true`). A separate verb from `setRetention` on purpose: "never expire" as a magic value passed
1151
1285
  * to the setter is how a typo becomes a deletion.
1152
1286
  */
1153
1287
  clearRetention(ref: SegmentRef): Promise<boolean>;
@@ -1169,20 +1303,22 @@ export declare class CloudRoaring {
1169
1303
  *
1170
1304
  * const swept = await store.retireExpired({ namespace: 'active-daily' });
1171
1305
  * for (const e of swept.entries) {
1172
- * if (e.action === 'skipped') console.warn(`${e.segment}: ${e.reason}`); // invalid-policy / limit / failed: …
1306
+ * // invalid-policy / policy-changed / tombstone-not-empty / failed: …
1307
+ * if (e.action === 'skipped') console.warn(`${e.segment}: ${e.reason}`);
1173
1308
  * if (e.action === 'retired' && e.result.generationsRemaining.length > 0) {
1174
1309
  * console.warn(`${e.segment}: storage not fully reclaimed — re-run`);
1175
1310
  * }
1176
1311
  * }
1177
- * if (swept.limited) scheduleAnotherPassSoon(); // more are still eligible
1312
+ * if (swept.limited) scheduleAnotherPassSoon(); // more work (retirements or purges) remains
1178
1313
  * ```
1179
1314
  *
1180
1315
  * **Read the ledger.** A per-segment *fault* is an entry, not an exception — a throw from the middle of a fleet
1181
1316
  * sweep would leave the caller unable to say which segments were retired, having already retired some. (A bad
1182
1317
  * argument does throw, and so does a fleet larger than `maxScanSegments`.) `limited: true` means the per-cycle
1183
- * `limit` (default 100) cut the pass short and more are eligible. That cap is charged on **attempts**, not
1184
- * successes, which is what makes it a real bound: `dropSegment` writes the tombstone before sweeping Storage, so a
1185
- * fault in the Storage phase is a segment that is already retired. Retirements are sequential, so `limit` is a
1318
+ * `limit` (default 100) cut the pass short, and more work (retirements or purges) remains: `limit` caps the
1319
+ * retirements and tombstone purges one call attempts, together, and a segment it deferred gets no entry. That cap
1320
+ * is charged on **attempts**, not successes, which is what makes it a real bound: `dropSegment` writes the
1321
+ * tombstone before sweeping Storage, so a fault in the Storage phase is a segment that is already retired. Retirements are sequential, so `limit` is a
1186
1322
  * wall-clock knob too, and `retired` counts deletions only — a dry run reports `wouldRetire` instead, so a
1187
1323
  * dashboard summing `retired` can never show a phantom deletion.
1188
1324
  *
@@ -1192,9 +1328,11 @@ export declare class CloudRoaring {
1192
1328
  * charged to `limit`, so it never holds the retirements behind it, and purging stops for the rest of the call after
1193
1329
  * three refused purges in a row (a purge that succeeds starts the count again).
1194
1330
  *
1195
- * It also **deletes the tombstone rows its own past retirements left**, after `tombstoneGraceMs` (default 24 h)
1331
+ * It also **deletes the tombstone rows its own past retirements left**, after `tombstoneGraceMs` (default 24 h; at least one hour, else `ValidationError`)
1196
1332
  * and only once that segment's Storage generations are provably gone — collecting a straggler generation itself
1197
- * first, since nothing else ever would for a tombstoned segment. Attribution is a **positive marker the sweep
1333
+ * first, since nothing else runs that collection on its own for a tombstoned segment (an erasure collects there
1334
+ * only
1335
+ * when an object holds its id, and a re-run drop sweeps it). Attribution is a **positive marker the sweep
1198
1336
  * stamps on its own retirements**, not an inference from "destroyed + an expired policy": a crypto-shred leaves
1199
1337
  * `retention` untouched, so setting a policy and then honouring a right-to-erasure request mid-window produces
1200
1338
  * exactly that row, and deleting it would destroy the Art. 17 attestation and un-fence the name. By default a
@@ -1294,8 +1432,9 @@ export declare class CloudRoaring {
1294
1432
  * throw). Read-only, bounded fan-out; run it at startup after a restore. Returns `{ checked, inconsistent,
1295
1433
  * errored }` — `inconsistent` empty ⇒ coherent; otherwise it names the segments to recover (restore the object
1296
1434
  * store, or roll the registry back to a coherent point). Needs the store built with a **backend**
1297
- * (throws {@link UnsupportedError} otherwise). `destroyed` (crypto-shredded) segments are skipped. Pair it with
1298
- * the DR runbook (docs/guide/disaster-recovery.md).
1435
+ * (throws {@link UnsupportedError} otherwise). `destroyed` segments (crypto-shredded, destroyed in the clear or
1436
+ * dropped) are skipped. Pair
1437
+ * it with the DR runbook (docs/guide/disaster-recovery.md).
1299
1438
  *
1300
1439
  * A segment whose pointer names a missing object is the torn restore this reports; a cold `count()` of it still
1301
1440
  * answers the number its row records, while a read of the object throws, so the count alone never shows it. With
@@ -1324,6 +1463,39 @@ export declare class CloudRoaring {
1324
1463
  summaries?: boolean;
1325
1464
  generations?: boolean;
1326
1465
  }): Promise<ConsistencyReport>;
1466
+ /**
1467
+ * **First-run check of the store's storage and registry.** Call it once at deploy time, or on a first run, before
1468
+ * the first load: it finds a missing permission, a storage that does not refuse a second write to a key, a listing
1469
+ * that lags, or a lifecycle rule that would delete the store's objects, while nothing depends on them yet.
1470
+ *
1471
+ * It runs seven checks and always lists all seven, in this order: `registry` (one read of a row that must be
1472
+ * absent, and the registry able to write), `write` (a new object), `write-once` (a second write to the same key must
1473
+ * be refused), `read` (the object reads back as written), `list` (the listing names it), `delete` (this run's own
1474
+ * object is removed, with the version the read gave where the driver applies one) and `lifecycle` (the backend's
1475
+ * lifecycle check). The probe is one small object at `cbm.due.preflight/segments/probe.<number>.crbm` under the
1476
+ * store's prefix; no registry row is written, and no segment of yours can share the name. A probe left by a run that
1477
+ * was cut off is named in the `list` detail and never deleted, since it could be a run in progress.
1478
+ *
1479
+ * It **never throws over a finding**. A failed step, a transient fault included, is a `problem` whose `detail`
1480
+ * says to run again when the fault was transient, and the checks that cannot run without it are `unchecked`. The
1481
+ * exception is the `lifecycle` step, whose failures, its timeout included, are `unchecked`. `ok` is true when no
1482
+ * check is a `problem`: read an `unchecked` check yourself, as `ok` does not vouch for it. The `lifecycle` check is
1483
+ * `unchecked` for a backend whose check says so (Azure Blob always), for a backend that has no such method (a
1484
+ * third-party backend, a `brandAsBackend` wrapper that does not forward it), when the identity lacks the optional
1485
+ * permission to read the lifecycle rules (`s3:GetLifecycleConfiguration`, `storage.buckets.get`), and when the check
1486
+ * takes longer than 30 seconds of the store's clock. The other steps are the store's ordinary calls and keep their
1487
+ * timing.
1488
+ *
1489
+ * **Not checked:** read-after-delete, the registry's `If-Match` on compare-and-swap, multipart abort permission,
1490
+ * versioning, backups, the keystore's backup and an S3 SDK from 3.641.0 to 3.699.0 (an older SDK shows as a
1491
+ * `write-once` problem; these drop `If-Match`, which only a registry write refuses). It makes no kind of request that a
1492
+ * load does not, though the lifecycle read needs its own optional permission. A run costs about seven requests (a
1493
+ * first run on GCS makes eight, the eighth a second listing that checks the bucket exists, and Azure Blob always
1494
+ * eight): two writes and a delete, the rest reads and one listing.
1495
+ *
1496
+ * Throws {@link UnsupportedError}, and only that, for a store with no backend, since there is nothing to check.
1497
+ */
1498
+ preflight(): Promise<PreflightResult>;
1327
1499
  /**
1328
1500
  * **Export ("eject") every registered segment's current generation** through the injected `sink`, using only
1329
1501
  * public read APIs — so your data is readable **without CloudRoaring** (the exit path; see the README's "Your
@@ -1332,8 +1504,9 @@ export declare class CloudRoaring {
1332
1504
  * Enumerates via the store's **own** registry (needs one — throws {@link UnsupportedError} otherwise) so the
1333
1505
  * enumeration and the read path provably share one registry. Encrypted segments are decrypted transparently
1334
1506
  * **iff** this store was wired with their keystore — the export is therefore **cleartext**; protect it.
1335
- * Crypto-shredded segments are skipped. A segment that can't be read is isolated into the manifest's `failed[]`
1336
- * (the run continues), so "a manifest exists" means the run finished — check `failed`. The `export-segments`
1507
+ * Destroyed segments (crypto-shredded, destroyed in the clear or dropped) are skipped. A segment that can't be read
1508
+ * is isolated into the manifest's `failed[]` (the run continues), so "a manifest exists" means the run finished —
1509
+ * check `failed`. The `export-segments`
1337
1510
  * CLI wraps this with a filesystem sink. The `'roaring'` format's bitmaps are built by the store's own codec.
1338
1511
  */
1339
1512
  exportSegments(sink: ExportSink, options?: ExportOptions): Promise<ExportManifest>;
@@ -1533,6 +1706,7 @@ export interface PinAt {
1533
1706
  export interface SegmentStat {
1534
1707
  /** The generation read, or `null` when the segment has none. */
1535
1708
  readonly generation: number | null;
1709
+ /** The number of ids in the generation read, or `0` when the segment has none. */
1536
1710
  readonly cardinality: number;
1537
1711
  /** The metadata the generation was loaded with; absent when it has none. */
1538
1712
  readonly metadata?: GenerationMetadata;
@@ -1601,7 +1775,7 @@ export declare class Segment {
1601
1775
  *
1602
1776
  * **One call reads a segment at one generation**, so a combine that holds this segment at two —
1603
1777
  * `snap0.andNot([snap1])`, or `live.intersect([snap])` — throws {@link ValidationError} when it is read, and an
1604
- * `*Into` of one throws before it reads anything. Materialise one side first, with `intersectInto(dest, [])`.
1778
+ * `*Into` of one throws before it reads anything. Materialise one side first, with `materializeMany({ operands: { src: seg }, outputs: [{ dest, expr: { or: ['src'] } }], keep })`.
1605
1779
  *
1606
1780
  * **A pin knows its object, not only its number.** A name purged and loaded again starts again at generation
1607
1781
  * 0, so a pin of the old segment never reads the new one: what it has already read still answers, as the
@@ -1702,10 +1876,10 @@ export declare class Segment {
1702
1876
  * `at.generation` instead of the current one. Pass what the earlier pin recorded, `{ generation, fingerprint }`
1703
1877
  * from its {@link Segment.pinnedAt}. A generation number alone is not an identity, since a purged and re-created
1704
1878
  * name starts again at 0, so the fingerprint is required: a bare number, a malformed fingerprint or a key other
1705
- * than `generation` and `fingerprint` is a {@link ValidationError}. Identify a pin by its `generation` and
1879
+ * than `generation`, `fingerprint` and `version` is a {@link ValidationError}. Identify a pin by its `generation` and
1706
1880
  * `fingerprint`: the handle's `pinnedAt.version` can differ from the earlier pin's.
1707
1881
  *
1708
- * Throws {@link NotFoundError} when the generation is gone (collected, purged, or on a crypto-shredded segment),
1882
+ * Throws {@link NotFoundError} when the generation is gone (collected, purged, or on a destroyed segment),
1709
1883
  * is above the row's pointer, or is another object than the fingerprint names, and never reads empty. A rollback
1710
1884
  * deletes nothing, so once a later load moves the pointer past a generation it rolled back from, that one can be
1711
1885
  * reopened while its object is stored. Nothing keeps a generation alive unless you lease it: a later load's
@@ -1718,6 +1892,10 @@ export declare class Segment {
1718
1892
  * then reads as one from `pin()` does, including its failure on a chunk it has not cached once the generation is
1719
1893
  * swept. Works for an encrypted segment. The first argument is an object so that fields can join it later; the lease
1720
1894
  * is in `options`, the second.
1895
+ *
1896
+ * It takes what {@link Segment.pinnedAt} holds: once `generation` is not `null`, the record passes as it is (its
1897
+ * `version` is not read), and `{ generation, fingerprint }` does as well. A pin of a segment that had no generation
1898
+ * has nothing to reopen and throws {@link ValidationError}.
1721
1899
  */
1722
1900
  pinAt(at: PinAt, options?: PinOptions): Promise<Segment>;
1723
1901
  /**
@@ -1728,15 +1906,25 @@ export declare class Segment {
1728
1906
  */
1729
1907
  key(): string;
1730
1908
  /**
1731
- * Refuse an `*Into` whose handles cannot be used, before any request: anything that is not a segment or is a
1732
- * segment of another store ({@link ValidationError}), and a handle (this one, `dest`, an operand or an exclude) whose
1733
- * lease has ended or was released ({@link LeaseExpiredError}). Called by the three `*Into` verbs only.
1909
+ * Refuse an `*Into` that cannot run, before any request, in this order: anything that is not a segment or is a
1910
+ * segment of another store, an empty operand list for `intersectInto`, and a `dest` that is also a source (all
1911
+ * {@link ValidationError}); then a handle (this one, `dest`, an operand or an exclude) whose lease has ended or was
1912
+ * released ({@link LeaseExpiredError}). A call with both a lapsed lease and one of the first three refusals throws the
1913
+ * first. Called by the three `*Into` verbs only.
1734
1914
  *
1735
1915
  * The verbs are `async` so this surfaces as a **rejected promise**, like every other validation in the facade —
1736
1916
  * a synchronous throw out of a promise-returning method escapes a caller who attached `.catch()` instead of
1737
1917
  * awaiting.
1738
1918
  */
1739
1919
  private assertIntoHandles;
1920
+ /**
1921
+ * Refuse an `*Into` whose destination is also one of its sources (this segment, an operand or an exclude, by the key
1922
+ * a handle gives, so a pin of the source and a ref spelled with the default namespace count), before any request, as
1923
+ * `materializeMany` refuses it. The combine would read the destination at the generation this store last resolved,
1924
+ * up to `cache.genTtlMs` old, while the publish is fenced on the row as it stands: another process's newer load of
1925
+ * the destination would be overwritten by a result built from the one before it, with no conflict to report.
1926
+ */
1927
+ private refuseSourceDestination;
1740
1928
  /** `result` as is, or, when a handle of the call holds a lease, checking that lease each time it reads a chunk. */
1741
1929
  private guarded;
1742
1930
  /**
@@ -1871,7 +2059,8 @@ export declare class Segment {
1871
2059
  *
1872
2060
  * Of {@link CombineOptions} it takes the range, `concurrency`, `budget`, `allowAbsentOperands` and `exclude`; a write
1873
2061
  * option (`audit`, `allowEmpty`, `guard`, `metadata`, `keep`) fails the stream with {@link ValidationError} when it is
1874
- * first read, before any request.
2062
+ * first read, before any request. So does an empty `others`: an intersection over nothing has no meaning, and
2063
+ * to read every id of one segment, use {@link iterate}. (`union` and `andNot` read an empty list as `this`.)
1875
2064
  */
1876
2065
  intersect(others: Segment[], options?: CombineOptions): IdStream;
1877
2066
  /**
@@ -1893,6 +2082,15 @@ export declare class Segment {
1893
2082
  * materialisation that silently did not take effect is the one thing a caller cannot detect on its own.
1894
2083
  *
1895
2084
  * A call involving a handle whose lease has ended, or anything that is not a segment, is refused before any of this.
2085
+ * So is a `dest` that is also `this`, an operand or an exclude (the same segment by name and namespace, however the
2086
+ * handle was made), and, for `intersectInto` alone, an empty `others` (`unionInto` and `andNotInto` publish `this` for an
2087
+ * empty list): each throws {@link ValidationError} before any request. A destination that
2088
+ * is also a source would publish a result built from the generation this store last resolved over a newer load by
2089
+ * another process, with no conflict to report. This release has no fenced in-place update: write the result into a
2090
+ * new segment and point readers at it; a single writer that knows nothing else writes the segment may load the result
2091
+ * back, unfenced. To copy `src` into `dest`, call
2092
+ * `materializeMany({ operands: { src }, outputs: [{ dest, expr: { or: ['src'] } }], keep })`, which reads each chunk
2093
+ * once, at one instant.
1896
2094
  * It takes every field of {@link CombineOptions}, as `unionInto` does.
1897
2095
  */
1898
2096
  intersectInto(dest: Segment, others: Segment[], options?: CombineOptions): Promise<MaterializeResult>;
@@ -1904,7 +2102,8 @@ export declare class Segment {
1904
2102
  * `intersect` prunes any key missing from any operand; union has nothing to prune. It is charged against the
1905
2103
  * same per-op budget, so a wide union is refused rather than quietly billed — pass `budget` to raise it
1906
2104
  * deliberately. If you find yourself unioning the same segments on every read, materializing the combined
1907
- * segment once (`unionInto`, or a load) is the cheaper shape. It takes the options {@link intersect} takes.
2105
+ * segment once (`unionInto`, or a load) is the cheaper shape. It takes the options {@link intersect} takes, and an
2106
+ * empty `others` reads `this` itself.
1908
2107
  */
1909
2108
  union(others: Segment[], options?: CombineOptions): IdStream;
1910
2109
  /** Materialize `this ∪ others…` (minus `exclude`) as a **new generation of `dest`** — see {@link intersectInto}. */
@@ -1938,6 +2137,9 @@ export declare class Segment {
1938
2137
  /** The one body of the three `*Into` verbs, after each has checked its own options. */
1939
2138
  private combineInto;
1940
2139
  }
2140
+ export { MemoryStorage, LocalFsStorage, InProcessKeystore } from '@cloudbitmaps/core/node';
2141
+ export type { InProcessKeystoreOptions, LocalFsStorageOptions, MemoryStorageOptions, } from '@cloudbitmaps/core/node';
1941
2142
  export { deserializePortable };
1942
- export { MemoryStorage, LocalFsStorage, destroySegment, eraseNamespace, excludingReservedRows, readRetentionPolicy, InProcessKeystore, CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, KeyUnavailableError, BudgetExceededError, LeaseExpiredError, LeaseLimitError, StaleOperandError, errorKind, CountingMetricsSink, RecordingAuditSink, } from '@cloudbitmaps/core';
1943
- export type { AuditEvent, Budget, BudgetOption, Clock, ConsistencyErrorEntry, ConsistencyIssue, ConsistencyReport, DestroyResult, DropResult, Entropy, EraseDeps, ErrorKind, ExportFailure, ExportFormat, ExportManifest, ExportOptions, ExportSink, ExportSkipped, ExportWriter, ExportedSegment, Expr, GenerationEntry, GenerationMetadata, IAuditSink, IMetricsSink, InProcessKeystoreOptions, LoadGuard, LoadInput, LoadOptions, LoadRefusal, LoadResult, LocalFsStorageOptions, MaterializeManyFeedRecord, MaterializeManyOperandStats, MaterializeManyOutputStats, MaterializeManyStats, MemoryStorageOptions, MetricEvent, MetricOpName, MetricsSnapshot, PinnedAt, PortableBitmap, RetentionPolicy, RetireEntry, RetireExpiredOptions, RetireExpiredResult, RetryPolicy, Rng, RollbackResult, SegmentInfo, SegmentRef, SetRetentionResult, } from '@cloudbitmaps/core';
2143
+ export type { ReadonlyBitmap } from './roaring-codec.js';
2144
+ export { excludingReservedRows, readRetentionPolicy, CloudRoaringError, ValidationError, WriteConflictError, IntegrityError, NotFoundError, UnsupportedError, CapabilityError, TransientError, KeyUnavailableError, BudgetExceededError, LeaseExpiredError, LeaseLimitError, StaleOperandError, errorKind, CountingMetricsSink, RecordingAuditSink, } from '@cloudbitmaps/core';
2145
+ export type { AuditEvent, Budget, BudgetOption, Clock, ConsistencyErrorEntry, ConsistencyIssue, ConsistencyReport, DestroyResult, DropResult, Entropy, EraseDeps, ErrorKind, ExportFailure, ExportFormat, ExportManifest, ExportOptions, ExportSink, ExportSkipped, ExportWriter, ExportedSegment, Expr, GenerationEntry, GenerationMetadata, IAuditSink, IMetricsSink, LoadGuard, LoadInput, LoadOptions, LoadRefusal, LoadResult, MaterializeManyFeedRecord, MaterializeManyOperandStats, MaterializeManyOutputStats, MaterializeManyStats, MetricEvent, MetricOpName, MetricsSnapshot, PinnedAt, PortableBitmap, PreflightCheck, PreflightResult, RetentionPolicy, RetireEntry, RetireExpiredOptions, RetireExpiredResult, RetryPolicy, Rng, RollbackResult, SegmentInfo, SegmentRef, SetRetentionResult, } from '@cloudbitmaps/core';