@cloudbitmaps/core 0.20.0 → 0.21.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 (75) hide show
  1. package/README.md +85 -0
  2. package/dist/{chunk-YSC7NJWV.js → chunk-IGLIZBR7.js} +740 -137
  3. package/dist/chunk-IGLIZBR7.js.map +7 -0
  4. package/dist/core/absent-operands.d.ts +8 -0
  5. package/dist/core/audit.d.ts +12 -2
  6. package/dist/core/bit-route.d.ts +2 -1
  7. package/dist/core/blob.d.ts +12 -1
  8. package/dist/core/bulk-load.d.ts +148 -0
  9. package/dist/core/cas-retry.d.ts +27 -0
  10. package/dist/core/check.d.ts +22 -0
  11. package/dist/core/chunk-checks.d.ts +6 -1
  12. package/dist/core/chunk-window.d.ts +11 -4
  13. package/dist/core/combine-expr.d.ts +1 -3
  14. package/dist/core/combine-feed.d.ts +2 -16
  15. package/dist/core/combine-many.d.ts +12 -9
  16. package/dist/core/concurrency.d.ts +8 -0
  17. package/dist/core/consistency.d.ts +69 -17
  18. package/dist/core/crbm/fingerprint.d.ts +5 -0
  19. package/dist/core/crbm/format.d.ts +0 -1
  20. package/dist/core/crbm/plan-reads.d.ts +9 -3
  21. package/dist/core/crbm/reader.d.ts +52 -6
  22. package/dist/core/crbm/varint.d.ts +2 -1
  23. package/dist/core/crbm/writer.d.ts +5 -1
  24. package/dist/core/crbm-open.d.ts +154 -0
  25. package/dist/core/crbm-storage-source.d.ts +65 -452
  26. package/dist/core/crbm-write.d.ts +75 -0
  27. package/dist/core/crypto.d.ts +6 -1
  28. package/dist/core/engine.d.ts +222 -33
  29. package/dist/core/erase-id.d.ts +42 -7
  30. package/dist/core/erasure.d.ts +4 -3
  31. package/dist/core/errors.d.ts +8 -2
  32. package/dist/core/generation-gc.d.ts +129 -15
  33. package/dist/core/generation-list.d.ts +11 -0
  34. package/dist/core/id-window.d.ts +46 -0
  35. package/dist/core/invalidation-scope.d.ts +77 -0
  36. package/dist/core/known-generations-shape.d.ts +13 -0
  37. package/dist/core/known-generations.d.ts +147 -0
  38. package/dist/core/leases.d.ts +4 -3
  39. package/dist/core/ledger-seed.d.ts +17 -0
  40. package/dist/core/load.d.ts +17 -38
  41. package/dist/core/lru.d.ts +2 -15
  42. package/dist/core/metrics.d.ts +4 -2
  43. package/dist/core/order.d.ts +2 -0
  44. package/dist/core/pinned-storage-source.d.ts +4 -4
  45. package/dist/core/ports.d.ts +89 -16
  46. package/dist/core/publish.d.ts +207 -0
  47. package/dist/core/registry-scan.d.ts +0 -2
  48. package/dist/core/retention-sweep.d.ts +69 -65
  49. package/dist/core/retention.d.ts +1 -1
  50. package/dist/core/retry.d.ts +12 -19
  51. package/dist/core/rollback.d.ts +60 -31
  52. package/dist/core/summary.d.ts +50 -18
  53. package/dist/core/token.d.ts +2 -2
  54. package/dist/core/validate.d.ts +2 -0
  55. package/dist/driver-kit.d.ts +4 -0
  56. package/dist/driver-kit.js +80 -7
  57. package/dist/driver-kit.js.map +3 -3
  58. package/dist/drivers/_shared/bytes.d.ts +6 -0
  59. package/dist/drivers/_shared/faults.d.ts +15 -0
  60. package/dist/drivers/_shared/object-keys.d.ts +18 -0
  61. package/dist/drivers/_shared/object-registry-keys.d.ts +0 -2
  62. package/dist/drivers/_shared/object-registry.d.ts +2 -0
  63. package/dist/drivers/_shared/options.d.ts +19 -0
  64. package/dist/drivers/_shared/registry.d.ts +13 -10
  65. package/dist/drivers/localfs/exact-case.d.ts +0 -3
  66. package/dist/drivers/localfs/fs-util.d.ts +22 -0
  67. package/dist/drivers/localfs/registry.d.ts +10 -4
  68. package/dist/drivers/localfs/storage.d.ts +9 -2
  69. package/dist/drivers/memory.d.ts +7 -4
  70. package/dist/index.d.ts +1 -1
  71. package/dist/index.js +3647 -2410
  72. package/dist/index.js.map +4 -4
  73. package/package.json +1 -1
  74. package/dist/chunk-YSC7NJWV.js.map +0 -7
  75. package/dist/core/kept-generations.d.ts +0 -40
@@ -37,7 +37,6 @@ export declare const FOOTER: {
37
37
  export declare const FOOTER_CRC_COVERAGE: 96;
38
38
  /** `flags` bit positions. */
39
39
  export declare const FLAG_ENCRYPTED: number;
40
- export declare const FLAG_INDEX_COMPRESSED: number;
41
40
  export declare const FLAG_LITTLE_ENDIAN: number;
42
41
  /**
43
42
  * The object carries an extension block just before its index (a generation's metadata). Set only when there is
@@ -34,11 +34,17 @@ export interface ChunkRegion {
34
34
  }
35
35
  /**
36
36
  * Plan the reads for `extents`: the needed chunks of one object, ascending by offset (the index lists chunks in key
37
- * order, which is object order), each at least a byte long, none overlapping another. The reads come back
38
- * ascending and disjoint, each covering one or more of the chunks, every chunk in exactly one read.
37
+ * order, which is object order), each at least a byte long, none overlapping another. The reads come out ascending
38
+ * and disjoint, each covering one or more of the chunks, every chunk in exactly one read.
39
+ *
40
+ * Lazy: the plan is a walk, so a consumer that takes the first reads pulls only the extents those reads cover (and
41
+ * the one after, which closes the last of them), and a plan over a very wide object costs nothing until it is read.
42
+ * Each extent is checked as the walk reaches it, before the read that would carry it is handed out, so no read ever
43
+ * covers an extent that was not checked; a plan taken to its end has checked them all. The reads are exactly the ones
44
+ * a plan made all at once would hold, in the same order.
39
45
  *
40
46
  * Throws {@link IntegrityError} for an extent that is not a pair of safe integers, or is outside `region`, or out of
41
47
  * order, or overlapping the one before it:
42
48
  * the index a plan is made from is untrusted bytes, and a read is never planned outside the chunk region.
43
49
  */
44
- export declare function planChunkReads(extents: readonly ChunkExtent[], region: ChunkRegion): readonly PlannedRead[];
50
+ export declare function planChunkReads(extents: Iterable<ChunkExtent>, region: ChunkRegion): Generator<PlannedRead, void, undefined>;
@@ -7,7 +7,7 @@ import type { ChunkRead, GenerationMetadata, ReadChunksOptions } from '../ports.
7
7
  * `cardinalityMinusOne` stores `cardinality - 1` because a chunk's cardinality runs `[1, 65536]` and 65,536 does
8
8
  * not fit a `u16`; an offset is a `f64` because an object past 4 GiB puts a payload beyond a `u32`.
9
9
  */
10
- export interface ParsedIndex {
10
+ interface ParsedIndex {
11
11
  readonly keys: Uint16Array;
12
12
  readonly cardinalityMinusOne: Uint16Array;
13
13
  readonly lengths: Uint32Array;
@@ -29,7 +29,12 @@ export declare const RETAINED_BYTES_PER_INDEX_ENTRY = 20;
29
29
  */
30
30
  export declare function indexCapacity(indexLength: number): number;
31
31
  export interface CrbmReaderOptions {
32
- /** Speculative tail size in bytes (default 256 KB; clamped up to at least the footer size). */
32
+ /**
33
+ * How many bytes the first tail read asks for, a whole number (default 256 KiB; clamped up to at least the footer
34
+ * size). Any value of at least an object's `tailBytes` opens it in that one read. Where an open keeps a small object's
35
+ * chunks (a `CrbmStorageChunkSource`'s does), it keeps them only when this read covers the whole object, so a value
36
+ * below the default can leave them to reads of their own.
37
+ */
33
38
  readonly tailBytes?: number;
34
39
  /** Hard cap on a single chunk payload length (default: the 1 MiB decode cap, plus the 28-byte nonce and tag on an encrypted object). The engine decodes under `maxBitmapBytes`; raise this with it. */
35
40
  readonly maxPayloadBytes?: number;
@@ -49,6 +54,20 @@ export interface CrbmReaderOptions {
49
54
  */
50
55
  readonly lineage?: unknown;
51
56
  }
57
+ /**
58
+ * Refuses a `size` that is not a whole byte count its own tail fits in. The size is the tier's word too: one that
59
+ * is not would turn off every bounds check an open makes against it.
60
+ */
61
+ export declare function checkSize(tail: Uint8Array, size: number): void;
62
+ /**
63
+ * What the footer of the object behind `blob` says with no key and no index, from one tail read of a footer's worth:
64
+ * whether it is encrypted, and its CRC (the one in {@link CrbmReader.fingerprint}). A footer that fails its own checks
65
+ * throws, as an open would.
66
+ */
67
+ export declare function readFooter(blob: BlobReader): Promise<{
68
+ readonly encrypted: boolean;
69
+ readonly footerCrc: number;
70
+ }>;
52
71
  /**
53
72
  * Whether the object behind `blob` says it is encrypted, from one tail read of a footer's worth, with no key and no
54
73
  * index; a footer that fails its own checks throws, as an open would. For a caller that must not open an object with
@@ -61,6 +80,14 @@ export declare function footerSaysEncrypted(blob: BlobReader): Promise<boolean>;
61
80
  * object and that region is at most `keepChunkBytesUpTo` bytes. Not exported from a package entry.
62
81
  */
63
82
  export declare function openCrbmReaderKeeping(blob: BlobReader, options: CrbmReaderOptions, keepChunkBytesUpTo: number | undefined): Promise<CrbmReader>;
83
+ /**
84
+ * How many bytes the first tail read of an open asks for: the caller's `tailBytes` or the default, and a footer's worth
85
+ * at least. Not exported from a package entry: {@link CrbmReader.open} and a caller that sends that read ahead of it
86
+ * ask for the same size.
87
+ */
88
+ export declare function openTailBytes(options: {
89
+ readonly tailBytes?: number;
90
+ }): number;
64
91
  export declare class CrbmReader {
65
92
  private readonly blob;
66
93
  private readonly objectSize;
@@ -102,6 +129,11 @@ export declare class CrbmReader {
102
129
  get fingerprint(): string;
103
130
  /** Total object bytes (from the one-GET tail read): the `sizeBytes` a segment's `stat()` reports. */
104
131
  get sizeBytes(): number;
132
+ /**
133
+ * The bytes of the object after its chunk payloads: any extension block, the index and the footer. A tail read of
134
+ * this many bytes covers all of them.
135
+ */
136
+ get tailBytes(): number;
105
137
  /**
106
138
  * Retained JS heap of this reader's parsed index — the weight the storage reader cache bounds on (a wide
107
139
  * segment's parsed index, not its payloads, dominates the reader's footprint): the exact byte length of the
@@ -134,6 +166,16 @@ export declare class CrbmReader {
134
166
  count(): number;
135
167
  /** The slot holding `chunkKey` (binary search over the ascending keys), or -1 when this generation has none. */
136
168
  private slotOf;
169
+ /**
170
+ * {@link slotOf} for a key at or after the one that held slot `at`, which a walk over ascending keys has: the slot
171
+ * itself or the next are tried first, so a read of nearly every chunk costs no search.
172
+ */
173
+ private slotFrom;
174
+ /**
175
+ * The extents of the chunks `chunkKeys` name that this generation holds, in key order, each once (a key given twice
176
+ * is read once). A walk, so nothing is looked up until the plan pulls it.
177
+ */
178
+ private neededExtents;
137
179
  has(chunkKey: number): boolean;
138
180
  /**
139
181
  * Range-GET one chunk's payload, verifying its CRC32C before returning. Returns `null` if the chunk is
@@ -168,10 +210,13 @@ export declare class CrbmReader {
168
210
  * as {@link getChunk} answers for an absent key. A key given twice is read once and answered at both positions with
169
211
  * the same view.
170
212
  *
171
- * The whole key list is planned once, up front, against this one generation's index. The ranges then run through a
172
- * window of `options.concurrency` reads ({@link MAX_RANGES_IN_FLIGHT} by default) that counts a range until the
173
- * consumer has taken it, so a stream never holds more than that many ranges, in flight or landed, however many keys
174
- * it was given or how slowly it is read; with `options.ramp` the window opens 1, 2, 4 … wide. A range is at most 1 MiB
213
+ * The key list is planned against this one generation's index ({@link planChunkReads}), as a walk the window pulls
214
+ * from only as it opens a range, so a stream that stops early has planned little: the same ranges, in the same
215
+ * order, as a plan of the whole list would make, and each chunk's extent is checked before the range that carries
216
+ * it is requested. The ranges run through a window of `options.concurrency` reads ({@link MAX_RANGES_IN_FLIGHT} by
217
+ * default) that counts a range until the consumer has taken it, so a stream never holds more than that many ranges,
218
+ * in flight or landed, however many keys it was given or how slowly it is read; with `options.ramp` the window opens
219
+ * 1, 2, 4 … wide. A range is at most 1 MiB
175
220
  * unless it is one chunk, which is at most the payload cap, so the bound is that many times the per-chunk cap
176
221
  * (1 MiB, and 28 bytes more for an encrypted chunk). Nothing is read until the first item is asked for, and a
177
222
  * consumer that stops launches no more: ranges already in flight finish and are dropped, and a failure of one of
@@ -223,3 +268,4 @@ export type ChunkStream = AsyncGenerator<Omit<ChunkRead, 'version'>> & {
223
268
  */
224
269
  export declare function parseExtension(sections: Uint8Array, crypto: CrbmCrypto | undefined): GenerationMetadata | undefined;
225
270
  export declare function parseIndex(indexBytes: Uint8Array, payloadEnd: number, maxPayloadBytes: number, minPayloadBytes?: number): ParsedIndex;
271
+ export {};
@@ -1,6 +1,6 @@
1
1
  /** Append the LEB128 encoding of a u32 `value` to `out`. */
2
2
  export declare function writeVarint(out: number[], value: number): void;
3
- export interface VarintRead {
3
+ interface VarintRead {
4
4
  readonly value: number;
5
5
  /** Offset just past the bytes consumed. */
6
6
  readonly next: number;
@@ -11,3 +11,4 @@ export interface VarintRead {
11
11
  * cleanly, never loop or overflow.
12
12
  */
13
13
  export declare function readVarint(bytes: Uint8Array, offset: number): VarintRead;
14
+ export {};
@@ -35,6 +35,8 @@ export declare class CrbmWriter {
35
35
  private readonly metadata;
36
36
  /** Bytes written so far, the footer included once {@link finish} has run. */
37
37
  private written;
38
+ /** Where the chunk payloads end: the extension block's start when there is metadata, else the index's. */
39
+ private payloadEnd;
38
40
  private footerCrc32c;
39
41
  constructor(sink: BlobSink, options: CrbmWriterOptions);
40
42
  /**
@@ -50,11 +52,13 @@ export declare class CrbmWriter {
50
52
  /**
51
53
  * The finished object's size and its footer's CRC: what names it, as a reader's fingerprint does. A writer that
52
54
  * has to tell its own object from another stored later under the same key compares these with the object's
53
- * footer. Throws before {@link finish}.
55
+ * footer. `tailBytes` is the bytes after the chunk payloads (any extension block, the index and the footer), which
56
+ * is what {@link CrbmReader.tailBytes} reports for the object. Throws before {@link finish}.
54
57
  */
55
58
  get identity(): {
56
59
  readonly size: number;
57
60
  readonly footerCrc: number;
61
+ readonly tailBytes: number;
58
62
  };
59
63
  private ensurePreamble;
60
64
  /**
@@ -0,0 +1,154 @@
1
+ import type { BlobReader } from './blob.js';
2
+ import type { CrbmCrypto } from './crypto.js';
3
+ import type { GenerationMetadata, GenKey, IStorageDriver, TailRead } from './ports.js';
4
+ import { CrbmReader } from './crbm/reader.js';
5
+ import type { CrbmReaderOptions } from './crbm/reader.js';
6
+ import type { SummaryDescription } from './summary.js';
7
+ /**
8
+ * Adapt one `(driver, key)` pair to the codec's `BlobReader` seam. With `noteTail`, each tail read the reader makes is
9
+ * shown to it with the bytes, `size` and `version` the driver answered, after the copy below when one is made.
10
+ *
11
+ * A tail's bytes reach the reader as a plain `Uint8Array`: the reader keeps a small object's chunk region by slicing
12
+ * the tail, and a subclass's `slice` need not copy. A Node `Buffer`'s is a view, so a driver that answered with one
13
+ * would leave the reader holding the driver's memory, all of it, as the cache weighs only the region. Such an answer
14
+ * is copied here, once ({@link ownedTail}); a plain `Uint8Array` of this realm, which every shipped driver returns, is
15
+ * handed through as it is.
16
+ */
17
+ export declare function storageBlobReader(driver: IStorageDriver, key: GenKey, noteTail?: (tail: TailRead) => void): BlobReader;
18
+ /**
19
+ * `tail` with its bytes in a plain `Uint8Array` of this realm. Any other `Uint8Array`, a subclass (a Node `Buffer`) or
20
+ * one made in another realm (a `vm` context), is copied once, and the copy is built from the answer's fields by name,
21
+ * so a `size` or `version` the driver serves from a getter on its own class carries over. The brand is read, not
22
+ * `instanceof`, which is false for another realm's arrays. A plain `Uint8Array` of this realm is handed through as it is.
23
+ */
24
+ export declare function ownedTail(tail: TailRead): TailRead;
25
+ /**
26
+ * The object under `key`, when one read of its footer matches `fingerprint` ({@link CrbmReader.fingerprint}), with the
27
+ * version the driver reported on that read (`undefined` from a driver that reports none). `null` when it is another
28
+ * object, when it is gone, and when the read fails in any way. A fingerprint names the object's bytes, not the writer:
29
+ * an object another writer stored under the number with the same bytes matches too. A caller that deletes what this
30
+ * matches passes the version as the delete's `ifVersion`, so a number taken again between the read and the delete keeps
31
+ * the object put under it since.
32
+ */
33
+ export declare function provenObject(storage: IStorageDriver, key: GenKey, fingerprint: string): Promise<{
34
+ readonly version: string | undefined;
35
+ } | null>;
36
+ /**
37
+ * Whether the object under `key` is still the one `fingerprint` names ({@link CrbmReader.fingerprint}), from one read
38
+ * of its footer. Unlike {@link provenObject}, a fault is not an answer: `NotFoundError` when the key holds no object,
39
+ * and any other failure of the read, thrown as it is.
40
+ */
41
+ export declare function sameObjectUnder(storage: IStorageDriver, key: GenKey, fingerprint: string): Promise<boolean>;
42
+ /**
43
+ * Whether the object under `key` says it is encrypted, from one read of its footer, with no key. `noteVersion` is shown
44
+ * the version the driver reported on that read, when it reported one: a caller that deletes the object for what its
45
+ * footer says passes it as the delete's `ifVersion`.
46
+ */
47
+ export declare function objectIsEncrypted(storage: IStorageDriver, key: GenKey, noteVersion?: (version: string) => void): Promise<boolean>;
48
+ /**
49
+ * What one tail read of a rollback target says about it with no key: whether the footer says it is encrypted and its
50
+ * CRC, and the remembered tail an open from it ({@link openRollbackTargetFrom}) is answered from.
51
+ */
52
+ interface RollbackTargetFooter {
53
+ readonly encrypted: boolean;
54
+ readonly footerCrc: number;
55
+ readonly blob: BlobReader;
56
+ }
57
+ /**
58
+ * The footer step of a rollback: one tail read of the object under `key`, which is remembered for the open that may
59
+ * follow. A footer that fails its own checks is an {@link IntegrityError}; a missing object is {@link NotFoundError}.
60
+ */
61
+ export declare function readRollbackTargetFooter(storage: IStorageDriver, key: GenKey): Promise<RollbackTargetFooter>;
62
+ /**
63
+ * The reader {@link RollbackTargetFooter}'s object opens as, from its remembered tail, when the object and the key
64
+ * agree (an encrypted object opened with `crypto`, a cleartext one with none); `undefined` when they disagree, which
65
+ * the caller refuses as a target the row cannot use. An object that is another generation's, and an index or metadata
66
+ * that do not open, are an {@link IntegrityError}.
67
+ */
68
+ export declare function openRollbackTargetFrom(footer: RollbackTargetFooter, key: GenKey, crypto: CrbmCrypto | undefined): Promise<CrbmReader | undefined>;
69
+ /**
70
+ * The footer CRC of the object under `key` ({@link CrbmReader.fingerprint} carries it), from one read of a footer's
71
+ * worth, so it reads an encrypted object's CRC as it does a cleartext one's, with no key. {@link NotFoundError} when
72
+ * the key holds no object; a footer that fails its own checks is an {@link IntegrityError}.
73
+ */
74
+ export declare function footerCrcUnder(storage: IStorageDriver, key: GenKey): Promise<number>;
75
+ /**
76
+ * Whether the object under `key` is the one `fingerprint` names, from one read of its footer: false when it is another
77
+ * object or gone. Unlike {@link provenObject}, a read that cannot tell throws, for a caller that must not take "could
78
+ * not look" for "not this object".
79
+ */
80
+ export declare function provesOwnObject(storage: IStorageDriver, key: GenKey, fingerprint: string): Promise<boolean>;
81
+ /**
82
+ * Open a {@link CrbmReader} on one generation over the storage driver's range/tail reads (decrypting if `crypto`).
83
+ * The reader the write paths use to re-read what they wrote, and the erasure rewrite uses to stream the old
84
+ * generation; the engine's read path goes through {@link CrbmStorageChunkSource} instead, which caches these. With
85
+ * `named`, the fingerprint the row's summary records, the object must be that one: another is {@link NotFoundError}.
86
+ * The version of the object it opened, from the tail read the open made, is what {@link objectVersionOf} answers.
87
+ */
88
+ export declare function openGenerationReader(storage: IStorageDriver, key: GenKey, crypto: CrbmCrypto | undefined, options?: Omit<CrbmReaderOptions, 'crypto'>, named?: string): Promise<CrbmReader>;
89
+ /**
90
+ * {@link openGenerationReader}, with `noteVersion` shown the version {@link objectVersionOf} would answer as soon as the
91
+ * tail read that carries it returns, before the open goes on: a caller whose open then fails, on an object sealed under
92
+ * another key, say, still knows which object it met, and can condition a delete of it on that read.
93
+ */
94
+ export declare function openGenerationReaderNoting(storage: IStorageDriver, key: GenKey, crypto: CrbmCrypto | undefined, noteVersion: (version: string) => void): Promise<CrbmReader>;
95
+ /**
96
+ * The version of the object `reader` was opened on, as the driver reported it on the tail read the open made, for a
97
+ * delete conditioned on that object ({@link StorageDeleteOptions.ifVersion}); `undefined` for a reader
98
+ * {@link openGenerationReader} did not open, or a driver that reports none. Held beside the reader rather than on it, so
99
+ * nothing is added to the reader's public surface, and no read the engine makes pays for it.
100
+ */
101
+ export declare function objectVersionOf(reader: CrbmReader): string | undefined;
102
+ /**
103
+ * {@link openGenerationReader}, of the object `summary.fingerprint` names: `undefined` when the object under the key is
104
+ * another one, found from its footer before its index is opened, so an object sealed under another key is told apart as
105
+ * well. The tail read is sized from the summary's `tailBytes` ({@link sizedTailBytes}), so a wide generation's index
106
+ * comes in that read.
107
+ */
108
+ export declare function openNamedGeneration(storage: IStorageDriver, key: GenKey, crypto: CrbmCrypto | undefined, summary: Pick<SummaryDescription, 'fingerprint' | 'tailBytes'>, noteTail?: (tail: TailRead) => void): Promise<CrbmReader | undefined>;
109
+ /**
110
+ * Open a reader on `key`, refusing an object whose footer names another generation. Every writer stamps the key's
111
+ * number, and the chunk cache, the load guard and the erasure rewrite all trust it, so an object that disagrees
112
+ * was written under another key or altered. Every open, the live read's, a pin's and the write paths', comes here.
113
+ * With `named`, the object must also be the one that fingerprint names: another one is {@link NotFoundError}, a move.
114
+ * With `early`, the tail read {@link startTailRead} began, the open takes that read as its own instead of making one.
115
+ */
116
+ export declare function openChecked(storage: IStorageDriver, key: GenKey, options: CrbmReaderOptions, keepChunkBytesUpTo?: number, named?: string, noteTail?: (tail: TailRead) => void, early?: Promise<TailRead>): Promise<CrbmReader>;
117
+ /**
118
+ * The size of the tail read an open makes when its row's summary says how many bytes of the object's end the open
119
+ * needs (`tailBytes`: any extension block, the index and the footer), so that one read reaches the index of a wide
120
+ * generation and no range read follows it. With no summary it is the source's own size ({@link openTailBytes}).
121
+ *
122
+ * The number came from a registry the library may not have written, so it only ever sizes a read: never below the
123
+ * source's own tail, at most the object less its preamble (the size its fingerprint names), and at most the source's
124
+ * `maxIndexBytes` (or the default) plus an extension block, its trailer and the footer, the most any open reads past
125
+ * its own tail. A hint that is not a whole number of bytes above zero is ignored, and so is a result that is not one. A
126
+ * wrong hint is a longer read or one more range read, never a different answer: the reader checks every byte it takes.
127
+ */
128
+ export declare function sizedTailBytes(summary: Pick<SummaryDescription, 'fingerprint' | 'tailBytes'> | undefined, options: {
129
+ readonly tailBytes?: number;
130
+ readonly maxIndexBytes?: number;
131
+ }): number;
132
+ /**
133
+ * Send the tail read an open of `key` makes, now, and hand back its answer for {@link openChecked}'s `early`: the open
134
+ * then waits on the one request instead of sending its own, so work the open waits on first, such as a keystore call,
135
+ * runs beside the request and not before it. Nothing is parsed here: the bytes are untrusted until the open reads them.
136
+ * The returned promise already has a handler attached, so a caller that never reaches the open (its key failed) leaves
137
+ * no unhandled rejection; the open that does reach it still sees the rejection.
138
+ */
139
+ export declare function startTailRead(storage: IStorageDriver, key: GenKey, options: CrbmReaderOptions): Promise<TailRead>;
140
+ /**
141
+ * Re-open a freshly written generation and assert it round-trips exactly what was streamed into it: the same
142
+ * per-chunk key set *and* the same total cardinality (on top of the codec's own per-chunk CRC + footer checks), and the
143
+ * metadata it was given. `expected` is the streaming writer's tally (the stream is consumed, so it can't be
144
+ * re-iterated) — the key-set comparison catches a dropped/extra chunk that a cardinality-only check could miss when
145
+ * two errors cancel out. The count and the metadata are what the generation's row summary is about to claim, so the
146
+ * summary is held to the object it describes before it is published.
147
+ * Throws {@link IntegrityError}: the object is on disk but must not be published.
148
+ */
149
+ export declare function verifyGeneration(storage: IStorageDriver, key: GenKey, expected: {
150
+ readonly chunkKeys: readonly number[];
151
+ readonly cardinality: number;
152
+ readonly metadata?: GenerationMetadata | undefined;
153
+ }, crypto: CrbmCrypto | undefined): Promise<void>;
154
+ export {};