@plane31/blind-relay 0.0.0-stage → 0.1.1

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 (135) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +26 -2
  3. package/dist/adapters/index.d.ts +18 -0
  4. package/dist/adapters/index.d.ts.map +1 -0
  5. package/dist/adapters/index.js +22 -0
  6. package/dist/adapters/index.js.map +1 -0
  7. package/dist/audience.d.ts +77 -0
  8. package/dist/audience.d.ts.map +1 -0
  9. package/dist/audience.js +76 -0
  10. package/dist/audience.js.map +1 -0
  11. package/dist/bytes.d.ts +54 -0
  12. package/dist/bytes.d.ts.map +1 -0
  13. package/dist/bytes.js +200 -0
  14. package/dist/bytes.js.map +1 -0
  15. package/dist/circle.d.ts +59 -0
  16. package/dist/circle.d.ts.map +1 -0
  17. package/dist/circle.js +105 -0
  18. package/dist/circle.js.map +1 -0
  19. package/dist/client.d.ts +234 -0
  20. package/dist/client.d.ts.map +1 -0
  21. package/dist/client.js +1365 -0
  22. package/dist/client.js.map +1 -0
  23. package/dist/codec.d.ts +189 -0
  24. package/dist/codec.d.ts.map +1 -0
  25. package/dist/codec.js +512 -0
  26. package/dist/codec.js.map +1 -0
  27. package/dist/crypto/backend.d.ts +39 -0
  28. package/dist/crypto/backend.d.ts.map +1 -0
  29. package/dist/crypto/backend.js +8 -0
  30. package/dist/crypto/backend.js.map +1 -0
  31. package/dist/crypto/noble.d.ts +3 -0
  32. package/dist/crypto/noble.d.ts.map +1 -0
  33. package/dist/crypto/noble.js +107 -0
  34. package/dist/crypto/noble.js.map +1 -0
  35. package/dist/crypto/sodium.d.ts +7 -0
  36. package/dist/crypto/sodium.d.ts.map +1 -0
  37. package/dist/crypto/sodium.js +39 -0
  38. package/dist/crypto/sodium.js.map +1 -0
  39. package/dist/crypto.d.ts +66 -0
  40. package/dist/crypto.d.ts.map +1 -0
  41. package/dist/crypto.js +225 -0
  42. package/dist/crypto.js.map +1 -0
  43. package/dist/epoch.d.ts +93 -0
  44. package/dist/epoch.d.ts.map +1 -0
  45. package/dist/epoch.js +121 -0
  46. package/dist/epoch.js.map +1 -0
  47. package/dist/errors.d.ts +17 -0
  48. package/dist/errors.d.ts.map +1 -0
  49. package/dist/errors.js +30 -0
  50. package/dist/errors.js.map +1 -0
  51. package/dist/historyIndex.d.ts +15 -0
  52. package/dist/historyIndex.d.ts.map +1 -0
  53. package/dist/historyIndex.js +57 -0
  54. package/dist/historyIndex.js.map +1 -0
  55. package/dist/identity.d.ts +62 -0
  56. package/dist/identity.d.ts.map +1 -0
  57. package/dist/identity.js +99 -0
  58. package/dist/identity.js.map +1 -0
  59. package/dist/inbox.d.ts +153 -0
  60. package/dist/inbox.d.ts.map +1 -0
  61. package/dist/inbox.js +472 -0
  62. package/dist/inbox.js.map +1 -0
  63. package/dist/index.d.ts +19 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +22 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/outbox.d.ts +96 -0
  68. package/dist/outbox.d.ts.map +1 -0
  69. package/dist/outbox.js +339 -0
  70. package/dist/outbox.js.map +1 -0
  71. package/dist/policy.d.ts +33 -0
  72. package/dist/policy.d.ts.map +1 -0
  73. package/dist/policy.js +71 -0
  74. package/dist/policy.js.map +1 -0
  75. package/dist/record.d.ts +49 -0
  76. package/dist/record.d.ts.map +1 -0
  77. package/dist/record.js +46 -0
  78. package/dist/record.js.map +1 -0
  79. package/dist/reset.d.ts +74 -0
  80. package/dist/reset.d.ts.map +1 -0
  81. package/dist/reset.js +127 -0
  82. package/dist/reset.js.map +1 -0
  83. package/dist/rows.d.ts +16 -0
  84. package/dist/rows.d.ts.map +1 -0
  85. package/dist/rows.js +103 -0
  86. package/dist/rows.js.map +1 -0
  87. package/dist/slots.d.ts +22 -0
  88. package/dist/slots.d.ts.map +1 -0
  89. package/dist/slots.js +38 -0
  90. package/dist/slots.js.map +1 -0
  91. package/dist/store.d.ts +357 -0
  92. package/dist/store.d.ts.map +1 -0
  93. package/dist/store.js +192 -0
  94. package/dist/store.js.map +1 -0
  95. package/dist/testing/clock.d.ts +14 -0
  96. package/dist/testing/clock.d.ts.map +1 -0
  97. package/dist/testing/clock.js +27 -0
  98. package/dist/testing/clock.js.map +1 -0
  99. package/dist/testing/fakeHost.d.ts +118 -0
  100. package/dist/testing/fakeHost.d.ts.map +1 -0
  101. package/dist/testing/fakeHost.js +462 -0
  102. package/dist/testing/fakeHost.js.map +1 -0
  103. package/dist/testing/faults.d.ts +97 -0
  104. package/dist/testing/faults.d.ts.map +1 -0
  105. package/dist/testing/faults.js +264 -0
  106. package/dist/testing/faults.js.map +1 -0
  107. package/dist/testing/fixtures.d.ts +15 -0
  108. package/dist/testing/fixtures.d.ts.map +1 -0
  109. package/dist/testing/fixtures.js +22 -0
  110. package/dist/testing/fixtures.js.map +1 -0
  111. package/dist/testing/index.d.ts +7 -0
  112. package/dist/testing/index.d.ts.map +1 -0
  113. package/dist/testing/index.js +7 -0
  114. package/dist/testing/index.js.map +1 -0
  115. package/dist/testing/providers.d.ts +16 -0
  116. package/dist/testing/providers.d.ts.map +1 -0
  117. package/dist/testing/providers.js +36 -0
  118. package/dist/testing/providers.js.map +1 -0
  119. package/dist/testing/sweep.d.ts +46 -0
  120. package/dist/testing/sweep.d.ts.map +1 -0
  121. package/dist/testing/sweep.js +366 -0
  122. package/dist/testing/sweep.js.map +1 -0
  123. package/dist/transactions.d.ts +75 -0
  124. package/dist/transactions.d.ts.map +1 -0
  125. package/dist/transactions.js +212 -0
  126. package/dist/transactions.js.map +1 -0
  127. package/dist/transport.d.ts +125 -0
  128. package/dist/transport.d.ts.map +1 -0
  129. package/dist/transport.js +6 -0
  130. package/dist/transport.js.map +1 -0
  131. package/dist/vault.d.ts +59 -0
  132. package/dist/vault.d.ts.map +1 -0
  133. package/dist/vault.js +69 -0
  134. package/dist/vault.js.map +1 -0
  135. package/package.json +66 -3
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Durable state (protocol section 11): the store interface the profile implements, the secret
3
+ * store, the logical tables, and an in-memory implementation with the same transaction semantics
4
+ * for Node tests.
5
+ *
6
+ * Rules the interface carries: one writer across every execution context; a transaction is
7
+ * atomic; the callback finishes synchronously, so the lock is never held across a suspension
8
+ * of the caller; the callback may initiate a transport send before commit through `tx.handoff`,
9
+ * and must not await it inside; a writer that cannot acquire the lock gets `LOCKED`.
10
+ */
11
+ import type { RecordKind } from "./codec.js";
12
+ export interface SecretStore {
13
+ get(name: SecretName): Promise<Uint8Array | undefined>;
14
+ set(name: SecretName, value: Uint8Array): Promise<void>;
15
+ delete(name: SecretName): Promise<void>;
16
+ }
17
+ export type SecretName = "accountSeed" | "deviceSeed" | "recoveryKey" | "storageKey" | "instanceId" | "pendingReset";
18
+ export type StoreState = "INITIALIZING" | "ACTIVE" | "ACTIVATION_PENDING" | "RETIRED";
19
+ export interface MetaRow {
20
+ schema: 1;
21
+ /** Set once the history index holds every history row; a store from before the index is backfilled on open. */
22
+ historyIndex?: 1;
23
+ /** Set once the newest slots are built from history; a store from before the slot table is rebuilt on open. */
24
+ newest?: 1;
25
+ instanceId: string;
26
+ accountName: string;
27
+ identityId: string;
28
+ certificateHash: string;
29
+ state: StoreState;
30
+ }
31
+ export interface SelfRow {
32
+ generation: string;
33
+ deviceId: string;
34
+ certificate: string;
35
+ certificateHash: string;
36
+ streamId: string;
37
+ }
38
+ export interface PinRow {
39
+ accountName: string;
40
+ accountKey: string;
41
+ identityId: string;
42
+ generation: string;
43
+ certificateHash: string;
44
+ certificate: string;
45
+ deviceId: string;
46
+ signingKey: string;
47
+ boxKey: string;
48
+ streamId: string;
49
+ deviceIds: string[];
50
+ }
51
+ export interface CertificateRow {
52
+ identityId: string;
53
+ certificateHash: string;
54
+ signingKey: string;
55
+ boxKey: string;
56
+ streamId: string;
57
+ generation: string;
58
+ wire: string;
59
+ current: boolean;
60
+ }
61
+ export interface QuarantineRow {
62
+ accountName: string;
63
+ certificate: string;
64
+ reason: string;
65
+ at: string;
66
+ }
67
+ export interface CircleRow {
68
+ circleId: string;
69
+ ownerIdentityId: string;
70
+ revision: string;
71
+ bodyHash: string | undefined;
72
+ snapshot: string | undefined;
73
+ members: string[];
74
+ enabled: boolean;
75
+ status: "requested" | "member" | "left" | "quarantined" | "closed";
76
+ verifiedAt: string;
77
+ /** An owner's successor snapshot awaiting host confirmation (T8). */
78
+ pending?: {
79
+ snapshot: string;
80
+ revision: string;
81
+ close?: boolean;
82
+ } | undefined;
83
+ }
84
+ export interface RevisionRow {
85
+ desiredRevision: string;
86
+ seenSnapshots: Record<string, string>;
87
+ seenCertificates: Record<string, string>;
88
+ paused: "rotation" | "metadata" | "limit" | "sync" | undefined;
89
+ }
90
+ export interface VaultRow {
91
+ revision: string;
92
+ hash: string;
93
+ wire: string;
94
+ /** Prepared but not yet confirmed by the host. */
95
+ pending: boolean;
96
+ /** The circle rows changed since this vault was derived from them; set in the same transaction. */
97
+ dirty: boolean;
98
+ }
99
+ export type EpochStatus = "prepared" | "committed" | "active" | "obsolete" | "retired";
100
+ export interface EpochRow {
101
+ epoch: number;
102
+ status: EpochStatus;
103
+ manifest: string;
104
+ manifestHash: string;
105
+ wraps: Record<string, string>;
106
+ epochKey: string;
107
+ capturedRevision: string;
108
+ audienceKey: string;
109
+ createdAt: string;
110
+ nextCounter: number;
111
+ lastSentAt: string | undefined;
112
+ }
113
+ export interface StreamRow {
114
+ highestCommittedEpoch: number;
115
+ activeEpoch: number | undefined;
116
+ pendingEpoch: number | undefined;
117
+ }
118
+ export type OutboxStatus = "queued" | "inflight" | "accepted" | "cancelled" | "unknown";
119
+ export interface OutboxRow {
120
+ recordId: string;
121
+ wire: string;
122
+ epoch: number;
123
+ counter: number;
124
+ kind: RecordKind;
125
+ sentAt: string;
126
+ desiredRevision: string;
127
+ status: OutboxStatus;
128
+ attempts: number;
129
+ reason: string | undefined;
130
+ }
131
+ export interface HistoryRow {
132
+ recordId: string;
133
+ authorIdentityId: string;
134
+ streamId: string;
135
+ generation: string;
136
+ epoch: number;
137
+ counter: number;
138
+ kind: RecordKind;
139
+ sentAt: string;
140
+ receivedAt: string;
141
+ plaintext: string;
142
+ superseded: boolean;
143
+ own: boolean;
144
+ /** Body hash of the wire, for duplicate and equivocation detection. */
145
+ bodyHash?: string;
146
+ /** The envelope's event time, when the sender gave one. */
147
+ eventTime?: string;
148
+ }
149
+ /**
150
+ * The newest record per author and kind (for kinds declared `newest`), keyed `<author>:<kind>`.
151
+ * The order fields decide replacement; the payload is dropped at expiry while the row keeps its
152
+ * order, so an older record replayed later cannot become current.
153
+ */
154
+ export interface NewestRow {
155
+ recordId: string;
156
+ bodyHash: string;
157
+ generation: string;
158
+ epoch: number;
159
+ counter: number;
160
+ sentAt: string;
161
+ receivedAt: string;
162
+ /** The event time the slot was ordered by, never later than `sentAt`. */
163
+ eventTime: string;
164
+ /** Hex, possibly empty; `null` once expired. */
165
+ payload: string | null;
166
+ }
167
+ export interface ReaderEpochRow {
168
+ streamId: string;
169
+ epoch: number;
170
+ epochKey: string;
171
+ manifestHash: string;
172
+ authorCertificateHash: string;
173
+ superseded: boolean;
174
+ }
175
+ export interface SubscriptionRow {
176
+ streamId: string;
177
+ authorIdentityId: string;
178
+ /** Local scan position: the last sequence examined. */
179
+ scanPos: string;
180
+ /** The eligible acknowledged prefix. */
181
+ ackPrefix: string;
182
+ /** The last cursor the relay confirmed. */
183
+ committedCursor: string;
184
+ /** A send in flight for this stream. */
185
+ ackInFlight: boolean;
186
+ }
187
+ export interface UnresolvedRow {
188
+ streamId: string;
189
+ deliverySeq: string;
190
+ reason: "KEY_PENDING";
191
+ epoch: number;
192
+ recordedAt: string;
193
+ }
194
+ export interface ActivationRow {
195
+ certificate: string;
196
+ vault: string;
197
+ vaultRevision: string;
198
+ expectedCertificateHash: string;
199
+ expectedVaultRevision: string;
200
+ expectedVaultHash: string;
201
+ }
202
+ export interface ResetListRow {
203
+ wire: string;
204
+ version: string;
205
+ hash: string;
206
+ checkedAt: string;
207
+ }
208
+ export interface ResetReceiptRow {
209
+ accountName: string;
210
+ oldIdentityId: string;
211
+ newIdentityId: string;
212
+ receiptHash: string;
213
+ }
214
+ export interface ClockRow {
215
+ highWater: string;
216
+ }
217
+ /** A last-resort reset prepared and persisted before it is sent, so a lost response can be resumed. */
218
+ export interface PendingResetRow {
219
+ resetId: string;
220
+ oldIdentityId: string;
221
+ certificate: string;
222
+ vault: string;
223
+ vaultHash: string;
224
+ }
225
+ /**
226
+ * One entry of the history index. Two keys point at every history row: `t:<kind>:<tuple>` for the
227
+ * timeline and `a:<author>:<kind>:<tuple>` for one author, where the tuple is the zero-padded
228
+ * `sentAt`, epoch and counter followed by the record id, so keys sort by time and never collide.
229
+ */
230
+ export interface HistoryIndexRow {
231
+ recordId: string;
232
+ }
233
+ /** A caller's idempotency key and the record it produced, kept for the delivery window. */
234
+ export interface EnqueueKeyRow {
235
+ recordId: string;
236
+ epoch: number;
237
+ counter: number;
238
+ sentAt: string;
239
+ }
240
+ export interface Tables {
241
+ meta: MetaRow;
242
+ self: SelfRow;
243
+ pins: PinRow;
244
+ certificates: CertificateRow;
245
+ quarantine: QuarantineRow;
246
+ circles: CircleRow;
247
+ revision: RevisionRow;
248
+ vault: VaultRow;
249
+ epochs: EpochRow;
250
+ stream: StreamRow;
251
+ outbox: OutboxRow;
252
+ history: HistoryRow;
253
+ historyIndex: HistoryIndexRow;
254
+ enqueueKeys: EnqueueKeyRow;
255
+ newest: NewestRow;
256
+ readerEpochs: ReaderEpochRow;
257
+ subscriptions: SubscriptionRow;
258
+ unresolved: UnresolvedRow;
259
+ activation: ActivationRow;
260
+ resetList: ResetListRow;
261
+ resetReceipts: ResetReceiptRow;
262
+ retiredIdentities: {
263
+ identityId: string;
264
+ };
265
+ clock: ClockRow;
266
+ pendingReset: PendingResetRow;
267
+ }
268
+ export type TableName = keyof Tables;
269
+ /** Bounds for `Tx.range`: every given bound applies; an absent one is open. */
270
+ export interface KeyRange {
271
+ readonly prefix?: string;
272
+ /** Inclusive lower bound. */
273
+ readonly gte?: string;
274
+ /** Exclusive lower bound. */
275
+ readonly gt?: string;
276
+ /** Exclusive upper bound. */
277
+ readonly lt?: string;
278
+ /** Inclusive upper bound. */
279
+ readonly lte?: string;
280
+ /** Descending key order when true. */
281
+ readonly reverse?: boolean;
282
+ readonly limit?: number;
283
+ }
284
+ /** Whether a key satisfies the bounds of a range (not its limit or order); shared by the stores. */
285
+ export declare function inKeyRange(key: string, q: KeyRange): boolean;
286
+ export interface Tx {
287
+ get<T extends TableName>(table: T, key: string): Tables[T] | undefined;
288
+ put<T extends TableName>(table: T, key: string, row: Tables[T]): void;
289
+ delete<T extends TableName>(table: T, key: string): void;
290
+ list<T extends TableName>(table: T, prefix?: string): readonly [string, Tables[T]][];
291
+ /**
292
+ * A bounded slice of a table in key order: the rows under `prefix` whose keys fall inside the
293
+ * bounds, ascending or descending, at most `limit` of them. The store serves it without reading
294
+ * the rest of the table.
295
+ */
296
+ range<T extends TableName>(table: T, q: KeyRange): readonly [string, Tables[T]][];
297
+ count(table: TableName): number;
298
+ /**
299
+ * Initiate a network operation inside this transaction (T6h). The call starts now, before
300
+ * commit; the returned promise is awaited by the caller after the transaction returns.
301
+ */
302
+ handoff<R>(start: () => Promise<R>): Promise<R>;
303
+ }
304
+ export interface Store {
305
+ /**
306
+ * BEGIN IMMEDIATE semantics: exclusive, atomic, serialised across every context. The callback
307
+ * runs to completion synchronously between begin and commit; a callback that returns a promise
308
+ * is refused with `STORAGE_FAILURE` and nothing is written. The one asynchronous thing a
309
+ * callback may do is start a network operation through `tx.handoff`.
310
+ */
311
+ transaction<R>(fn: (tx: Tx) => R): Promise<R>;
312
+ /** A consistent read without taking the writer lock. */
313
+ read<R>(fn: (tx: Omit<Tx, "put" | "delete" | "handoff">) => R): Promise<R>;
314
+ }
315
+ /**
316
+ * Run a transaction callback and refuse one that returns a promise. Shared by every `Store`
317
+ * implementation so the refusal is the same error everywhere.
318
+ */
319
+ export declare function invokeSync<R>(fn: (tx: Tx) => R, tx: Tx): R;
320
+ type TableMap = Map<TableName, Map<string, unknown>>;
321
+ /** Crash injection for tests: throw at a chosen point. */
322
+ export interface MemoryStoreOptions {
323
+ /** Called just before a transaction commits; throwing simulates a crash before durability. */
324
+ beforeCommit?: (count: number) => void;
325
+ }
326
+ interface Shared {
327
+ tables: TableMap;
328
+ chain: Promise<void>;
329
+ held: boolean;
330
+ commits: number;
331
+ }
332
+ export declare class MemoryStore implements Store {
333
+ private readonly options;
334
+ private readonly shared;
335
+ /** Every handoff started inside a committed transaction, for tests that wait for the network. */
336
+ readonly handoffs: Promise<unknown>[];
337
+ constructor(options?: MemoryStoreOptions, shared?: Shared);
338
+ transaction<R>(fn: (tx: Tx) => R): Promise<R>;
339
+ read<R>(fn: (tx: Omit<Tx, "put" | "delete" | "handoff">) => R): Promise<R>;
340
+ /** One writer at a time across every handle on the same tables, like SQLite's file lock. */
341
+ private acquire;
342
+ /** A second handle on the same tables and lock, as another execution context would have. */
343
+ fork(): MemoryStore;
344
+ get isHeld(): boolean;
345
+ get commitCount(): number;
346
+ snapshot(): Record<string, Record<string, unknown>>;
347
+ }
348
+ export declare class MemorySecretStore implements SecretStore {
349
+ private readonly items;
350
+ /** Test hook: throw on the next write to simulate a crash between the two stores. */
351
+ failNextWrite: boolean;
352
+ get(name: SecretName): Promise<Uint8Array | undefined>;
353
+ set(name: SecretName, value: Uint8Array): Promise<void>;
354
+ delete(name: SecretName): Promise<void>;
355
+ }
356
+ export {};
357
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/store.js ADDED
@@ -0,0 +1,192 @@
1
+ import { KavachError } from "./errors.js";
2
+ /** Whether a key satisfies the bounds of a range (not its limit or order); shared by the stores. */
3
+ export function inKeyRange(key, q) {
4
+ if (q.prefix !== undefined && !key.startsWith(q.prefix))
5
+ return false;
6
+ if (q.gte !== undefined && key < q.gte)
7
+ return false;
8
+ if (q.gt !== undefined && key <= q.gt)
9
+ return false;
10
+ if (q.lt !== undefined && key >= q.lt)
11
+ return false;
12
+ if (q.lte !== undefined && key > q.lte)
13
+ return false;
14
+ return true;
15
+ }
16
+ // In-memory implementation -----------------------------------------------------------------------
17
+ /**
18
+ * Run a transaction callback and refuse one that returns a promise. Shared by every `Store`
19
+ * implementation so the refusal is the same error everywhere.
20
+ */
21
+ export function invokeSync(fn, tx) {
22
+ const result = fn(tx);
23
+ if (isThenable(result))
24
+ throw new KavachError("STORAGE_FAILURE", "store", "transaction callbacks are synchronous");
25
+ return result;
26
+ }
27
+ function isThenable(value) {
28
+ return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.then === "function";
29
+ }
30
+ function cloneRow(row) {
31
+ return JSON.parse(JSON.stringify(row));
32
+ }
33
+ class MemoryTx {
34
+ base;
35
+ readOnly;
36
+ journal = new Map();
37
+ handoffs = [];
38
+ constructor(base, readOnly) {
39
+ this.base = base;
40
+ this.readOnly = readOnly;
41
+ }
42
+ tableJournal(table) {
43
+ let j = this.journal.get(table);
44
+ if (!j) {
45
+ j = new Map();
46
+ this.journal.set(table, j);
47
+ }
48
+ return j;
49
+ }
50
+ get(table, key) {
51
+ const j = this.journal.get(table);
52
+ if (j && j.has(key)) {
53
+ const v = j.get(key);
54
+ return v === null ? undefined : cloneRow(v);
55
+ }
56
+ const v = this.base.get(table)?.get(key);
57
+ return v === undefined ? undefined : cloneRow(v);
58
+ }
59
+ put(table, key, row) {
60
+ if (this.readOnly)
61
+ throw new KavachError("STORAGE_FAILURE", "store", "write in a read transaction");
62
+ this.tableJournal(table).set(key, cloneRow(row));
63
+ }
64
+ delete(table, key) {
65
+ if (this.readOnly)
66
+ throw new KavachError("STORAGE_FAILURE", "store", "write in a read transaction");
67
+ this.tableJournal(table).set(key, null);
68
+ }
69
+ list(table, prefix = "") {
70
+ const merged = new Map(this.base.get(table) ?? []);
71
+ for (const [k, v] of this.journal.get(table) ?? []) {
72
+ if (v === null)
73
+ merged.delete(k);
74
+ else
75
+ merged.set(k, v);
76
+ }
77
+ return [...merged.entries()]
78
+ .filter(([k]) => k.startsWith(prefix))
79
+ .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))
80
+ .map(([k, v]) => [k, cloneRow(v)]);
81
+ }
82
+ range(table, q) {
83
+ const rows = this.list(table, q.prefix).filter(([k]) => inKeyRange(k, q));
84
+ if (q.reverse)
85
+ rows.reverse();
86
+ return q.limit === undefined ? rows : rows.slice(0, Math.max(0, q.limit));
87
+ }
88
+ count(table) {
89
+ return this.list(table).length;
90
+ }
91
+ handoff(start) {
92
+ if (this.readOnly)
93
+ throw new KavachError("STORAGE_FAILURE", "store", "handoff in a read transaction");
94
+ const p = start();
95
+ this.handoffs.push(p.catch(() => undefined));
96
+ return p;
97
+ }
98
+ commitInto(base) {
99
+ for (const [table, j] of this.journal) {
100
+ let t = base.get(table);
101
+ if (!t) {
102
+ t = new Map();
103
+ base.set(table, t);
104
+ }
105
+ for (const [k, v] of j) {
106
+ if (v === null)
107
+ t.delete(k);
108
+ else
109
+ t.set(k, v);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ export class MemoryStore {
115
+ options;
116
+ shared;
117
+ /** Every handoff started inside a committed transaction, for tests that wait for the network. */
118
+ handoffs = [];
119
+ constructor(options = {}, shared) {
120
+ this.options = options;
121
+ this.shared = shared ?? { tables: new Map(), chain: Promise.resolve(), held: false, commits: 0 };
122
+ }
123
+ async transaction(fn) {
124
+ const release = await this.acquire();
125
+ try {
126
+ const tx = new MemoryTx(this.shared.tables, false);
127
+ const result = invokeSync(fn, tx);
128
+ this.options.beforeCommit?.(this.shared.commits + 1);
129
+ tx.commitInto(this.shared.tables);
130
+ this.shared.commits++;
131
+ this.handoffs.push(...tx.handoffs);
132
+ return result;
133
+ }
134
+ finally {
135
+ release();
136
+ }
137
+ }
138
+ async read(fn) {
139
+ return fn(new MemoryTx(this.shared.tables, true));
140
+ }
141
+ /** One writer at a time across every handle on the same tables, like SQLite's file lock. */
142
+ acquire() {
143
+ const previous = this.shared.chain;
144
+ let release = () => undefined;
145
+ this.shared.chain = new Promise((resolve) => {
146
+ release = () => {
147
+ this.shared.held = false;
148
+ resolve();
149
+ };
150
+ });
151
+ return previous.then(() => {
152
+ this.shared.held = true;
153
+ return release;
154
+ });
155
+ }
156
+ /** A second handle on the same tables and lock, as another execution context would have. */
157
+ fork() {
158
+ return new MemoryStore(this.options, this.shared);
159
+ }
160
+ get isHeld() {
161
+ return this.shared.held;
162
+ }
163
+ get commitCount() {
164
+ return this.shared.commits;
165
+ }
166
+ snapshot() {
167
+ const out = {};
168
+ for (const [t, m] of this.shared.tables)
169
+ out[t] = Object.fromEntries([...m.entries()].map(([k, v]) => [k, cloneRow(v)]));
170
+ return out;
171
+ }
172
+ }
173
+ export class MemorySecretStore {
174
+ items = new Map();
175
+ /** Test hook: throw on the next write to simulate a crash between the two stores. */
176
+ failNextWrite = false;
177
+ async get(name) {
178
+ const v = this.items.get(name);
179
+ return v ? Uint8Array.from(v) : undefined;
180
+ }
181
+ async set(name, value) {
182
+ if (this.failNextWrite) {
183
+ this.failNextWrite = false;
184
+ throw new KavachError("STORAGE_FAILURE", "secretStore", "simulated crash");
185
+ }
186
+ this.items.set(name, Uint8Array.from(value));
187
+ }
188
+ async delete(name) {
189
+ this.items.delete(name);
190
+ }
191
+ }
192
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { RetentionPolicy } from "../policy.js";
2
+ /**
3
+ * A retention policy for tests. Three kinds: 0 is kept a day in history with a newest slot
4
+ * (a position); 1 is kept thirty days in history with no slot, every one news (an event); 2 is a
5
+ * one-day slot only, latest wins while queued (a state).
6
+ */
7
+ export declare const testPolicy: RetentionPolicy;
8
+ /** A controllable clock. */
9
+ export declare class TestClock {
10
+ t: bigint;
11
+ now: () => bigint;
12
+ advance(ms: bigint): void;
13
+ }
14
+ //# sourceMappingURL=clock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.d.ts","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD;;;;GAIG;AACH,eAAO,MAAM,UAAU,EAAE,eAYxB,CAAC;AAEF,4BAA4B;AAC5B,qBAAa,SAAS;IACpB,CAAC,SAAsB;IACvB,GAAG,QAAO,MAAM,CAAW;IAC3B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;CAG1B"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * A retention policy for tests. Three kinds: 0 is kept a day in history with a newest slot
3
+ * (a position); 1 is kept thirty days in history with no slot, every one news (an event); 2 is a
4
+ * one-day slot only, latest wins while queued (a state).
5
+ */
6
+ export const testPolicy = {
7
+ version: 1,
8
+ deliveryWindowMs: 86400000n,
9
+ appendRetryWindowMs: 604800000n,
10
+ hygieneRotationMs: 2592000000n,
11
+ maxOutboxRecords: 2000,
12
+ maxOutboxBytes: 4 << 20,
13
+ kinds: [
14
+ { kind: 0, retentionMs: 86400000n, queue: "keepAll", history: true, newest: true, headerClass: 0 },
15
+ { kind: 1, retentionMs: 2592000000n, queue: "keepAll", history: true, newest: false, headerClass: 1 },
16
+ { kind: 2, retentionMs: 86400000n, queue: "latestWins", history: false, newest: true, headerClass: 2 }
17
+ ]
18
+ };
19
+ /** A controllable clock. */
20
+ export class TestClock {
21
+ t = 1700000000000n;
22
+ now = () => this.t;
23
+ advance(ms) {
24
+ this.t += ms;
25
+ }
26
+ }
27
+ //# sourceMappingURL=clock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clock.js","sourceRoot":"","sources":["../../src/testing/clock.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,UAAU,GAAoB;IACzC,OAAO,EAAE,CAAC;IACV,gBAAgB,EAAE,SAAW;IAC7B,mBAAmB,EAAE,UAAY;IACjC,iBAAiB,EAAE,WAAc;IACjC,gBAAgB,EAAE,IAAI;IACtB,cAAc,EAAE,CAAC,IAAI,EAAE;IACvB,KAAK,EAAE;QACL,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,SAAW,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;QACpG,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,WAAc,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE;QACxG,EAAE,IAAI,EAAE,CAAC,EAAE,WAAW,EAAE,SAAW,EAAE,KAAK,EAAE,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,EAAE;KACzG;CACF,CAAC;AAEF,4BAA4B;AAC5B,MAAM,OAAO,SAAS;IACpB,CAAC,GAAG,cAAkB,CAAC;IACvB,GAAG,GAAG,GAAW,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3B,OAAO,CAAC,EAAU;QAChB,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACf,CAAC;CACF"}