@plane31/blind-relay 0.0.0-stage → 0.1.2

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 (169) 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 +9 -0
  36. package/dist/crypto/sodium.d.ts.map +1 -0
  37. package/dist/crypto/sodium.js +51 -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 +67 -3
  136. package/src/adapters/index.ts +102 -0
  137. package/src/audience.ts +123 -0
  138. package/src/bytes.ts +209 -0
  139. package/src/circle.ts +127 -0
  140. package/src/client.ts +1442 -0
  141. package/src/codec.ts +642 -0
  142. package/src/crypto/backend.ts +48 -0
  143. package/src/crypto/noble.ts +104 -0
  144. package/src/crypto/node-module.d.ts +11 -0
  145. package/src/crypto/sodium.ts +53 -0
  146. package/src/crypto.ts +266 -0
  147. package/src/epoch.ts +201 -0
  148. package/src/errors.ts +78 -0
  149. package/src/historyIndex.ts +61 -0
  150. package/src/identity.ts +158 -0
  151. package/src/inbox.ts +560 -0
  152. package/src/index.ts +59 -0
  153. package/src/outbox.ts +385 -0
  154. package/src/policy.ts +88 -0
  155. package/src/record.ts +106 -0
  156. package/src/reset.ts +176 -0
  157. package/src/rows.ts +116 -0
  158. package/src/slots.ts +55 -0
  159. package/src/store.ts +557 -0
  160. package/src/testing/clock.ts +29 -0
  161. package/src/testing/fakeHost.ts +482 -0
  162. package/src/testing/faults.ts +321 -0
  163. package/src/testing/fixtures.ts +35 -0
  164. package/src/testing/index.ts +6 -0
  165. package/src/testing/providers.ts +39 -0
  166. package/src/testing/sweep.ts +407 -0
  167. package/src/transactions.ts +231 -0
  168. package/src/transport.ts +106 -0
  169. package/src/vault.ts +126 -0
@@ -0,0 +1,96 @@
1
+ import { type RetentionPolicy } from "./policy.js";
2
+ import type { Store, Tx } from "./store.js";
3
+ import type { AppendOutcome, Relay } from "./transport.js";
4
+ import { type RecordKind } from "./codec.js";
5
+ export interface OutboxEvents {
6
+ queued?(recordId: Uint8Array, kind: RecordKind): void;
7
+ accepted?(recordId: Uint8Array): void;
8
+ cancelled?(recordId: Uint8Array, reason: string): void;
9
+ /** A record of a kind with a newest slot was cancelled or is in doubt: the app may resend its current state of that kind. */
10
+ refresh?(reason: string): void;
11
+ securityError?(code: string, detail: string): void;
12
+ }
13
+ export interface OutboxDeps {
14
+ readonly store: Store;
15
+ readonly relay: Relay;
16
+ readonly policy: RetentionPolicy;
17
+ readonly now: () => bigint;
18
+ readonly author: () => {
19
+ streamId: Uint8Array;
20
+ signingSecretKey: Uint8Array;
21
+ generation: bigint;
22
+ identityId: Uint8Array;
23
+ };
24
+ readonly events?: OutboxEvents;
25
+ }
26
+ export interface EnqueueOptions {
27
+ /**
28
+ * A caller-chosen key for this hand-over, derived from the sample itself (its fix time and
29
+ * source, say). The guarantee: a keyed enqueue that returns has committed its record and the
30
+ * key in one transaction; a second enqueue under the same key, from a retry after a crash or
31
+ * from another runtime on the same store, returns that record with `duplicate: true` and seals
32
+ * nothing, concurrent calls included, since the store's writer lock orders them; a refused
33
+ * enqueue stores no key, so its retry is checked again. The key is kept for the delivery
34
+ * window and covers the hand-over, not delivery: the record it names can still be cancelled by
35
+ * a rotation, which the `cancelled` event reports as for any record. Up to 128 characters.
36
+ */
37
+ readonly idempotencyKey?: string;
38
+ /**
39
+ * The event time of what the record describes (a fix time, say), carried in the encrypted
40
+ * envelope. A reader orders the kind's newest slot by it, clamped to the send time. Absent for a
41
+ * kind with no natural event time; the slot then orders by send time. Zero means absent: the
42
+ * envelope has no other way to say "none", and the sender's own slot follows the same reading.
43
+ */
44
+ readonly eventTime?: bigint;
45
+ }
46
+ export interface Enqueued {
47
+ recordId: Uint8Array;
48
+ counter: number;
49
+ epoch: number;
50
+ /** True when the idempotency key matched an earlier enqueue and this call made no record. */
51
+ duplicate: boolean;
52
+ /** True when this record took the sender's own newest slot for its kind. */
53
+ own: boolean;
54
+ }
55
+ export declare const MAX_IDEMPOTENCY_KEY = 128;
56
+ /**
57
+ * T6: require a usable active epoch under the current desired revision, enforce the queue limits,
58
+ * seal once, write the outbox row and the own history row, and advance the counter. The record
59
+ * id is returned only after commit. A kind declared latestWins cancels a queued record of the same
60
+ * kind when a newer one is enqueued, never a sent one; a slot-only kind writes no history row. An
61
+ * idempotency key is answered before any check: its record is already durable, whatever has
62
+ * happened to the queue since.
63
+ */
64
+ export declare function enqueue(deps: OutboxDeps, kind: RecordKind, payload: Uint8Array, options?: EnqueueOptions): Promise<Enqueued>;
65
+ export interface DrainSummary {
66
+ sent: number;
67
+ accepted: number;
68
+ cancelled: number;
69
+ unknown: number;
70
+ retry: number;
71
+ }
72
+ /**
73
+ * The single serialised sender: one record in flight per stream, drained in (epoch, counter)
74
+ * order. Each handoff is T6h: re-check eligibility, mark in flight, start the send inside the
75
+ * transaction, commit; the response is awaited outside and recorded in a new transaction that
76
+ * revalidates first.
77
+ */
78
+ export declare function drain(deps: OutboxDeps, maxRecords?: number): Promise<DrainSummary>;
79
+ type Final = "accepted" | "cancelled" | "unknown" | "retry";
80
+ export declare function recordOutcome(deps: OutboxDeps, key: string, outcome: AppendOutcome | undefined): Promise<Final>;
81
+ /** Retention for rows that will not be sent again: they go once the delivery window has passed. */
82
+ export declare function purgeOutbox(store: Store, policy: RetentionPolicy, now: bigint): Promise<number>;
83
+ export interface OutboxCounts {
84
+ readonly queued: number;
85
+ readonly inflight: number;
86
+ readonly cancelled: number;
87
+ readonly unknown: number;
88
+ /** Age of the oldest row still to send, when there is one. */
89
+ readonly oldestPendingAgeMs: bigint | undefined;
90
+ }
91
+ /** Rows by state, for diagnostics. */
92
+ export declare function outboxCounts(tx: Pick<Tx, "list">, now: bigint): OutboxCounts;
93
+ /** Rows still waiting, for state reporting. */
94
+ export declare function outboxCount(store: Store): Promise<number>;
95
+ export {};
96
+ //# sourceMappingURL=outbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.d.ts","sourceRoot":"","sources":["../src/outbox.ts"],"names":[],"mappings":"AAQA,OAAO,EAAU,KAAK,eAAe,EAAE,MAAM,aAAa,CAAC;AAI3D,OAAO,KAAK,EAAyB,KAAK,EAAE,EAAE,EAAE,MAAM,YAAY,CAAC;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,GAAG,IAAI,CAAC;IACtD,QAAQ,CAAC,CAAC,QAAQ,EAAE,UAAU,GAAG,IAAI,CAAC;IACtC,SAAS,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACvD,6HAA6H;IAC7H,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,aAAa,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM;QAAE,QAAQ,EAAE,UAAU,CAAC;QAAC,gBAAgB,EAAE,UAAU,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,UAAU,CAAA;KAAE,CAAC;IAC1H,QAAQ,CAAC,MAAM,CAAC,EAAE,YAAY,CAAC;CAChC;AASD,MAAM,WAAW,cAAc;IAC7B;;;;;;;;;OASG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC;;;;;OAKG;IACH,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,UAAU,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,6FAA6F;IAC7F,SAAS,EAAE,OAAO,CAAC;IACnB,4EAA4E;IAC5E,GAAG,EAAE,OAAO,CAAC;CACd;AAED,eAAO,MAAM,mBAAmB,MAAM,CAAC;AAEvC;;;;;;;GAOG;AACH,wBAAsB,OAAO,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,QAAQ,CAAC,CA8GtI;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAKD;;;;;GAKG;AACH,wBAAsB,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,SAAO,GAAG,OAAO,CAAC,YAAY,CAAC,CAuBtF;AA6DD,KAAK,KAAK,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,GAAG,OAAO,CAAC;AAE5D,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAAC,KAAK,CAAC,CAyCrH;AAED,mGAAmG;AACnG,wBAAsB,WAAW,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAarG;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,8DAA8D;IAC9D,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,SAAS,CAAC;CACjD;AAED,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,YAAY,CAY5E;AAED,+CAA+C;AAC/C,wBAAsB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAE/D"}
package/dist/outbox.js ADDED
@@ -0,0 +1,339 @@
1
+ /**
2
+ * The outbox and the sender (protocol section 10, publishing; transactions T6 and T6h).
3
+ */
4
+ import { fromHex, toHex } from "./bytes.js";
5
+ import { rotationReason, MAX_COUNTER } from "./epoch.js";
6
+ import { bodyHash } from "./crypto.js";
7
+ import { KavachError } from "./errors.js";
8
+ import { indexHistory } from "./historyIndex.js";
9
+ import { kindOf } from "./policy.js";
10
+ import { clampEventTime, takeSlot } from "./slots.js";
11
+ import { sealRecord } from "./record.js";
12
+ import { big, unbig } from "./rows.js";
13
+ import { META, REVISION, STREAM, currentRevision, t3ApplyChange } from "./transactions.js";
14
+ import { recordWireBytes } from "./codec.js";
15
+ function requireReady(tx) {
16
+ const meta = tx.get("meta", META);
17
+ if (!meta)
18
+ throw new KavachError("RECOVERY_REQUIRED", "enqueue", "no header");
19
+ if (meta.state === "RETIRED")
20
+ throw new KavachError("SUPERSEDED_DEVICE", "enqueue", "this device is retired");
21
+ if (meta.state !== "ACTIVE")
22
+ throw new KavachError("ACCOUNT_RECOVERY_REQUIRED", "enqueue", `store is ${meta.state}`);
23
+ }
24
+ export const MAX_IDEMPOTENCY_KEY = 128;
25
+ /**
26
+ * T6: require a usable active epoch under the current desired revision, enforce the queue limits,
27
+ * seal once, write the outbox row and the own history row, and advance the counter. The record
28
+ * id is returned only after commit. A kind declared latestWins cancels a queued record of the same
29
+ * kind when a newer one is enqueued, never a sent one; a slot-only kind writes no history row. An
30
+ * idempotency key is answered before any check: its record is already durable, whatever has
31
+ * happened to the queue since.
32
+ */
33
+ export async function enqueue(deps, kind, payload, options = {}) {
34
+ const stage = "enqueue";
35
+ const declared = kindOf(deps.policy, kind);
36
+ if (!declared)
37
+ throw new KavachError("MALFORMED", stage, `kind ${kind} is not declared in the retention policy`);
38
+ const key = options.idempotencyKey;
39
+ if (key !== undefined && (key.length === 0 || key.length > MAX_IDEMPOTENCY_KEY))
40
+ throw new KavachError("MALFORMED", stage, "idempotency key must be 1 to 128 characters");
41
+ // One reading of the event time for the envelope, the own slot and the history row: zero is none.
42
+ const eventTime = options.eventTime === undefined || options.eventTime === 0n ? undefined : options.eventTime;
43
+ if (eventTime !== undefined && eventTime < 0n)
44
+ throw new KavachError("MALFORMED", stage, "event time before the epoch");
45
+ const superseded = [];
46
+ const result = await deps.store.transaction((tx) => {
47
+ requireReady(tx);
48
+ if (key !== undefined) {
49
+ const seen = tx.get("enqueueKeys", key);
50
+ if (seen)
51
+ return { recordId: fromHex(seen.recordId), counter: seen.counter, epoch: seen.epoch, duplicate: true, own: false };
52
+ }
53
+ const revision = tx.get("revision", REVISION);
54
+ if (revision?.paused === "metadata")
55
+ throw new KavachError("METADATA_REQUIRED", stage);
56
+ if (revision?.paused === "limit")
57
+ throw new KavachError("RECIPIENT_LIMIT", stage);
58
+ const stream = tx.get("stream", STREAM);
59
+ if (!stream || stream.activeEpoch === undefined || revision?.paused === "rotation")
60
+ throw new KavachError("ROTATION_REQUIRED", stage, "no active epoch");
61
+ const epoch = tx.get("epochs", String(stream.activeEpoch));
62
+ if (!epoch || epoch.status !== "active")
63
+ throw new KavachError("ROTATION_REQUIRED", stage, "epoch not active");
64
+ const now = deps.now();
65
+ const reason = rotationReason({ createdAt: unbig(epoch.createdAt), nextCounter: epoch.nextCounter, lastSentAt: epoch.lastSentAt === undefined ? undefined : unbig(epoch.lastSentAt) }, now, deps.policy.hygieneRotationMs);
66
+ if (reason) {
67
+ // Commit the invalidation (T3) and report the rotation after the transaction, so the
68
+ // burned counters and cancelled rows are durable even though nothing was enqueued.
69
+ t3ApplyChange(tx, { kind: reason });
70
+ return { rotate: reason };
71
+ }
72
+ let count = 0;
73
+ let bytes = 0;
74
+ for (const [key, row] of tx.list("outbox")) {
75
+ if (declared.queue === "latestWins" && row.kind === kind && row.status === "queued") {
76
+ tx.put("outbox", key, terminal(row, "cancelled", "superseded"));
77
+ superseded.push(fromHex(row.recordId));
78
+ continue;
79
+ }
80
+ if (row.status === "queued" || row.status === "inflight") {
81
+ count++;
82
+ bytes += row.wire.length / 2;
83
+ }
84
+ }
85
+ if (count >= deps.policy.maxOutboxRecords || bytes + recordWireBytes(payload.length) > deps.policy.maxOutboxBytes)
86
+ throw new KavachError("QUEUE_FULL", stage);
87
+ const a = deps.author();
88
+ const sealed = sealRecord({
89
+ streamId: a.streamId,
90
+ epoch: epoch.epoch,
91
+ nextCounter: epoch.nextCounter,
92
+ kind,
93
+ eventTime,
94
+ headerClass: declared.headerClass,
95
+ payload,
96
+ sentAt: now,
97
+ epochKey: fromHex(epoch.epochKey),
98
+ signingSecretKey: a.signingSecretKey
99
+ });
100
+ const id = toHex(sealed.recordId);
101
+ tx.put("outbox", id, {
102
+ recordId: id,
103
+ wire: toHex(sealed.wire),
104
+ epoch: epoch.epoch,
105
+ counter: sealed.counter,
106
+ kind,
107
+ sentAt: big(now),
108
+ desiredRevision: big(currentRevision(tx)),
109
+ status: "queued",
110
+ attempts: 0,
111
+ reason: undefined
112
+ });
113
+ if (key !== undefined)
114
+ tx.put("enqueueKeys", key, { recordId: id, epoch: epoch.epoch, counter: sealed.counter, sentAt: big(now) });
115
+ // The sender's own row, under the rules a reader applies (section 10): history when the kind
116
+ // keeps it, and the own newest slot when the kind has one, so `newest` answers for self.
117
+ const self = toHex(a.identityId);
118
+ const hash = toHex(bodyHash(sealed.wire.subarray(0, sealed.wire.length - 64)));
119
+ const own = declared.newest ? takeSlot(tx, self, kind, { generation: a.generation, eventTime: clampEventTime(eventTime, now), epoch: epoch.epoch, counter: sealed.counter, recordId: id, bodyHash: hash, sentAt: now, receivedAt: now, payload }, toHex) : false;
120
+ if (declared.history) {
121
+ const ownRow = {
122
+ recordId: id,
123
+ authorIdentityId: toHex(a.identityId),
124
+ streamId: toHex(a.streamId),
125
+ generation: big(a.generation),
126
+ epoch: epoch.epoch,
127
+ counter: sealed.counter,
128
+ kind,
129
+ sentAt: big(now),
130
+ receivedAt: big(now),
131
+ plaintext: toHex(payload),
132
+ superseded: false,
133
+ own: true,
134
+ ...(eventTime === undefined ? {} : { eventTime: big(eventTime) })
135
+ };
136
+ tx.put("history", id, ownRow);
137
+ indexHistory(tx, ownRow);
138
+ }
139
+ const nextCounter = epoch.nextCounter + 1;
140
+ tx.put("epochs", String(epoch.epoch), { ...epoch, nextCounter, lastSentAt: big(now) });
141
+ if (nextCounter > MAX_COUNTER) {
142
+ // The final counter was just used: the next enqueue rotates.
143
+ }
144
+ return { recordId: sealed.recordId, counter: sealed.counter, epoch: epoch.epoch, duplicate: false, own };
145
+ });
146
+ if ("rotate" in result) {
147
+ throw new KavachError(result.rotate === "counterExhausted" ? "COUNTER_EXHAUSTED" : "ROTATION_REQUIRED", stage, result.rotate);
148
+ }
149
+ if (result.duplicate)
150
+ return result;
151
+ for (const id of superseded)
152
+ deps.events?.cancelled?.(id, "superseded");
153
+ deps.events?.queued?.(result.recordId, kind);
154
+ return result;
155
+ }
156
+ /**
157
+ * The single serialised sender: one record in flight per stream, drained in (epoch, counter)
158
+ * order. Each handoff is T6h: re-check eligibility, mark in flight, start the send inside the
159
+ * transaction, commit; the response is awaited outside and recorded in a new transaction that
160
+ * revalidates first.
161
+ */
162
+ export async function drain(deps, maxRecords = 1000) {
163
+ const summary = { sent: 0, accepted: 0, cancelled: 0, unknown: 0, retry: 0 };
164
+ for (let i = 0; i < maxRecords; i++) {
165
+ const step = await handoffNext(deps, summary);
166
+ if (step.kind === "none")
167
+ break;
168
+ if (step.kind === "skipped")
169
+ continue; // a cancelled row counts against the limit, never ends the drain
170
+ summary.sent++;
171
+ let outcome;
172
+ try {
173
+ outcome = await step.outcome;
174
+ }
175
+ catch {
176
+ outcome = undefined; // lost response
177
+ }
178
+ const final = await recordOutcome(deps, step.key, outcome);
179
+ if (final === "accepted")
180
+ summary.accepted++;
181
+ else if (final === "cancelled")
182
+ summary.cancelled++;
183
+ else if (final === "unknown")
184
+ summary.unknown++;
185
+ else {
186
+ summary.retry++;
187
+ break; // a retryable failure ends this drain; the next sync re-enters T6h
188
+ }
189
+ }
190
+ return summary;
191
+ }
192
+ /** Dead rows cancelled per handoff transaction; a larger backlog is finished over the next handoffs. */
193
+ const CANCEL_BATCH = 500;
194
+ /** A row that will not be sent again keeps its summary and sheds the ciphertext. */
195
+ function terminal(row, status, reason) {
196
+ return { ...row, wire: "", status, reason };
197
+ }
198
+ async function handoffNext(deps, summary) {
199
+ // Application events fire after the commit, never from inside it: a subscriber cannot roll a
200
+ // transition back, and never sees state the store has not kept yet.
201
+ const after = [];
202
+ const step = await deps.store.transaction((tx) => {
203
+ const meta = tx.get("meta", META);
204
+ if (!meta || meta.state !== "ACTIVE")
205
+ return { kind: "none" };
206
+ const now = deps.now();
207
+ const revision = currentRevision(tx);
208
+ // One pass: every row that is no longer sendable (its revision moved on, or its window has
209
+ // passed) is cancelled here, in bounded batches, and the first sendable row goes out in the
210
+ // same transaction. A backlog of dead rows costs one scan, not one transaction per row.
211
+ const live = [];
212
+ let cancelled = 0;
213
+ let refresh = false;
214
+ for (const [key, row] of [...tx.list("outbox")].sort(([, a], [, b]) => a.epoch - b.epoch || a.counter - b.counter)) {
215
+ if (row.status !== "queued" && row.status !== "inflight")
216
+ continue;
217
+ const reason = cancelled >= CANCEL_BATCH ? undefined : unbig(row.desiredRevision) !== revision ? "rotation" : unbig(row.sentAt) + deps.policy.deliveryWindowMs <= now ? "expired" : undefined;
218
+ if (!reason) {
219
+ live.push([key, row]);
220
+ continue;
221
+ }
222
+ tx.put("outbox", key, terminal(row, "cancelled", reason));
223
+ cancelled++;
224
+ after.push(() => deps.events?.cancelled?.(fromHex(row.recordId), reason));
225
+ if (reason === "rotation" && kindOf(deps.policy, row.kind)?.newest)
226
+ refresh = true;
227
+ }
228
+ summary.cancelled += cancelled;
229
+ if (refresh)
230
+ after.push(() => deps.events?.refresh?.("rotation"));
231
+ // A full batch means unchecked rows remain: finish them in the next handoff before sending.
232
+ if (cancelled >= CANCEL_BATCH)
233
+ return { kind: "skipped" };
234
+ const next = live.find(([, r]) => r.status === "inflight") ?? live[0];
235
+ if (!next)
236
+ return { kind: "none" };
237
+ const [key, row] = next;
238
+ const marked = { ...row, status: "inflight", attempts: row.attempts + 1 };
239
+ tx.put("outbox", key, marked);
240
+ let outcome;
241
+ try {
242
+ outcome = tx.handoff(() => deps.relay.appendRecord(fromHex(row.recordId), fromHex(row.wire)));
243
+ }
244
+ catch {
245
+ // A synchronous transport failure: roll the in-flight mark back and stop this drain.
246
+ tx.put("outbox", key, { ...row, attempts: row.attempts + 1 });
247
+ summary.retry++;
248
+ return { kind: "none" };
249
+ }
250
+ return { kind: "sent", key, row: marked, outcome };
251
+ });
252
+ for (const fire of after)
253
+ fire();
254
+ return step;
255
+ }
256
+ export async function recordOutcome(deps, key, outcome) {
257
+ const after = [];
258
+ const final = await deps.store.transaction((tx) => {
259
+ const row = tx.get("outbox", key);
260
+ if (!row || row.status !== "inflight")
261
+ return "retry";
262
+ const id = fromHex(row.recordId);
263
+ const requeue = () => tx.put("outbox", key, { ...row, status: "queued", reason: undefined });
264
+ const cancel = (reason) => tx.put("outbox", key, terminal(row, "cancelled", reason));
265
+ if (!outcome) {
266
+ requeue(); // lost response: retry the identical bytes; the relay answers from its checkpoint
267
+ return "retry";
268
+ }
269
+ switch (outcome.status) {
270
+ case "ACCEPTED":
271
+ case "ALREADY_ACCEPTED":
272
+ tx.delete("outbox", key);
273
+ after.push(() => deps.events?.accepted?.(id));
274
+ return "accepted";
275
+ case "RETRYABLE":
276
+ requeue();
277
+ return "retry";
278
+ case "STALE_APPEND":
279
+ tx.put("outbox", key, terminal(row, "unknown", "STALE_APPEND"));
280
+ after.push(() => deps.events?.cancelled?.(id, "acceptanceUnknown"));
281
+ if (kindOf(deps.policy, row.kind)?.newest)
282
+ after.push(() => deps.events?.refresh?.("acceptanceUnknown"));
283
+ return "unknown";
284
+ case "EQUIVOCATION":
285
+ cancel("EQUIVOCATION");
286
+ after.push(() => deps.events?.securityError?.("EQUIVOCATION", "the relay holds a different record under this id"));
287
+ return "cancelled";
288
+ case "EPOCH_FENCED":
289
+ case "SUPERSEDED_DEVICE":
290
+ case "UNAUTHORIZED":
291
+ cancel(outcome.status);
292
+ after.push(() => deps.events?.cancelled?.(id, outcome.status));
293
+ if (kindOf(deps.policy, row.kind)?.newest)
294
+ after.push(() => deps.events?.refresh?.(outcome.status));
295
+ return "cancelled";
296
+ }
297
+ });
298
+ for (const fire of after)
299
+ fire();
300
+ return final;
301
+ }
302
+ /** Retention for rows that will not be sent again: they go once the delivery window has passed. */
303
+ export async function purgeOutbox(store, policy, now) {
304
+ return store.transaction((tx) => {
305
+ let purged = 0;
306
+ for (const [key, row] of tx.list("outbox")) {
307
+ if ((row.status === "cancelled" || row.status === "unknown") && unbig(row.sentAt) + policy.deliveryWindowMs <= now) {
308
+ tx.delete("outbox", key);
309
+ purged++;
310
+ }
311
+ }
312
+ // Idempotency keys outlive the delivery window by nothing: a replay later is a new record.
313
+ for (const [key, row] of tx.list("enqueueKeys"))
314
+ if (unbig(row.sentAt) + policy.deliveryWindowMs <= now)
315
+ tx.delete("enqueueKeys", key);
316
+ return purged;
317
+ });
318
+ }
319
+ /** Rows by state, for diagnostics. */
320
+ export function outboxCounts(tx, now) {
321
+ const counts = { queued: 0, inflight: 0, cancelled: 0, unknown: 0 };
322
+ let oldest;
323
+ for (const [, r] of tx.list("outbox")) {
324
+ if (r.status === "accepted")
325
+ continue;
326
+ counts[r.status]++;
327
+ if (r.status === "queued" || r.status === "inflight") {
328
+ const sentAt = unbig(r.sentAt);
329
+ if (oldest === undefined || sentAt < oldest)
330
+ oldest = sentAt;
331
+ }
332
+ }
333
+ return { ...counts, oldestPendingAgeMs: oldest === undefined ? undefined : now - oldest };
334
+ }
335
+ /** Rows still waiting, for state reporting. */
336
+ export async function outboxCount(store) {
337
+ return store.read((tx) => tx.list("outbox").filter(([, r]) => r.status === "queued" || r.status === "inflight").length);
338
+ }
339
+ //# sourceMappingURL=outbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outbox.js","sourceRoot":"","sources":["../src/outbox.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ /** How the SDK treats one record kind; what the kind means is the product's. */
2
+ export interface KindDeclaration {
3
+ /** The kind number carried by the record. Until revision 8 the wire carries 0, 1 or 2. */
4
+ readonly kind: number;
5
+ /** How long a reader keeps records and the newest slot's payload, from `sentAt`. */
6
+ readonly retentionMs: bigint;
7
+ /** `keepAll`: every queued record is sent. `latestWins`: a newer queued record of this kind cancels the older one (`superseded`). */
8
+ readonly queue: "keepAll" | "latestWins";
9
+ /** Whether records are kept in indexed, pageable history. */
10
+ readonly history: boolean;
11
+ /** Whether one newest-per-author slot is kept, from the author's current device, ordered by event time. */
12
+ readonly newest: boolean;
13
+ /** The two header bits the relay may see for this kind (0 to 3, 0 when absent), for routing and notifications without content. */
14
+ readonly headerClass: 0 | 1 | 2 | 3;
15
+ }
16
+ export interface RetentionPolicy {
17
+ readonly version: number;
18
+ readonly deliveryWindowMs: bigint;
19
+ readonly appendRetryWindowMs: bigint;
20
+ readonly hygieneRotationMs: bigint;
21
+ readonly maxOutboxRecords: number;
22
+ readonly maxOutboxBytes: number;
23
+ readonly kinds: readonly KindDeclaration[];
24
+ }
25
+ /** The largest kind the envelope carries. */
26
+ export declare const MAX_WIRE_KIND = 255;
27
+ /** A missing or malformed policy is rejected; the SDK never substitutes defaults. */
28
+ export declare function validatePolicy(policy: unknown): RetentionPolicy;
29
+ /** The declaration of a kind, or `undefined` for one the product did not declare. */
30
+ export declare function kindOf(policy: RetentionPolicy, kind: number): KindDeclaration | undefined;
31
+ /** The kinds kept in history, in declaration order. */
32
+ export declare function historyKinds(policy: RetentionPolicy): readonly number[];
33
+ //# sourceMappingURL=policy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAOA,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,0FAA0F;IAC1F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,qIAAqI;IACrI,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,YAAY,CAAC;IACzC,6DAA6D;IAC7D,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,2GAA2G;IAC3G,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,kIAAkI;IAClI,QAAQ,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;IACrC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,KAAK,EAAE,SAAS,eAAe,EAAE,CAAC;CAC5C;AAED,6CAA6C;AAC7C,eAAO,MAAM,aAAa,MAAM,CAAC;AAIjC,qFAAqF;AACrF,wBAAgB,cAAc,CAAC,MAAM,EAAE,OAAO,GAAG,eAAe,CAsC/D;AAED,qFAAqF;AACrF,wBAAgB,MAAM,CAAC,MAAM,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEzF;AAED,uDAAuD;AACvD,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,MAAM,EAAE,CAEvE"}
package/dist/policy.js ADDED
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The versioned retention policy a profile passes to `open()` (protocol section 13): the global
3
+ * windows, and one declaration per record kind the product uses. The SDK treats a kind as an
4
+ * opaque small integer whose behaviour is what the declaration says. No defaults.
5
+ */
6
+ import { KavachError } from "./errors.js";
7
+ /** The largest kind the envelope carries. */
8
+ export const MAX_WIRE_KIND = 255;
9
+ const FIELDS = ["version", "deliveryWindowMs", "appendRetryWindowMs", "hygieneRotationMs", "maxOutboxRecords", "maxOutboxBytes", "kinds"];
10
+ /** A missing or malformed policy is rejected; the SDK never substitutes defaults. */
11
+ export function validatePolicy(policy) {
12
+ const stage = "policy";
13
+ if (typeof policy !== "object" || policy === null)
14
+ throw new KavachError("MALFORMED", stage, "retention policy missing");
15
+ const p = policy;
16
+ for (const f of FIELDS)
17
+ if (!(f in p))
18
+ throw new KavachError("MALFORMED", stage, `retention policy lacks ${f}`);
19
+ const big = (f, v) => {
20
+ if (typeof v !== "bigint" || v <= 0n)
21
+ throw new KavachError("MALFORMED", stage, `${f} must be a positive bigint`);
22
+ return v;
23
+ };
24
+ const int = (f, v) => {
25
+ if (typeof v !== "number" || !Number.isInteger(v) || v <= 0)
26
+ throw new KavachError("MALFORMED", stage, `${f} must be a positive integer`);
27
+ return v;
28
+ };
29
+ if (!Array.isArray(p.kinds) || p.kinds.length === 0)
30
+ throw new KavachError("MALFORMED", stage, "kinds must declare at least one kind");
31
+ const seen = new Set();
32
+ const kinds = p.kinds.map((raw, i) => {
33
+ if (typeof raw !== "object" || raw === null)
34
+ throw new KavachError("MALFORMED", stage, `kinds[${i}] must be an object`);
35
+ const k = raw;
36
+ const kind = k.kind;
37
+ if (typeof kind !== "number" || !Number.isInteger(kind) || kind < 0 || kind > MAX_WIRE_KIND)
38
+ throw new KavachError("MALFORMED", stage, `kinds[${i}].kind must be an integer from 0 to ${MAX_WIRE_KIND}`);
39
+ if (seen.has(kind))
40
+ throw new KavachError("MALFORMED", stage, `kind ${kind} declared twice`);
41
+ seen.add(kind);
42
+ if (k.queue !== "keepAll" && k.queue !== "latestWins")
43
+ throw new KavachError("MALFORMED", stage, `kinds[${i}].queue must be keepAll or latestWins`);
44
+ if (typeof k.history !== "boolean" || typeof k.newest !== "boolean")
45
+ throw new KavachError("MALFORMED", stage, `kinds[${i}].history and .newest must be booleans`);
46
+ if (!k.history && !k.newest)
47
+ throw new KavachError("MALFORMED", stage, `kinds[${i}] keeps nothing: declare history or newest`);
48
+ const headerClass = k.headerClass ?? 0;
49
+ if (headerClass !== 0 && headerClass !== 1 && headerClass !== 2 && headerClass !== 3)
50
+ throw new KavachError("MALFORMED", stage, `kinds[${i}].headerClass must be 0 to 3`);
51
+ return { kind, retentionMs: big(`kinds[${i}].retentionMs`, k.retentionMs), queue: k.queue, history: k.history, newest: k.newest, headerClass };
52
+ });
53
+ return {
54
+ version: int("version", p.version),
55
+ deliveryWindowMs: big("deliveryWindowMs", p.deliveryWindowMs),
56
+ appendRetryWindowMs: big("appendRetryWindowMs", p.appendRetryWindowMs),
57
+ hygieneRotationMs: big("hygieneRotationMs", p.hygieneRotationMs),
58
+ maxOutboxRecords: int("maxOutboxRecords", p.maxOutboxRecords),
59
+ maxOutboxBytes: int("maxOutboxBytes", p.maxOutboxBytes),
60
+ kinds
61
+ };
62
+ }
63
+ /** The declaration of a kind, or `undefined` for one the product did not declare. */
64
+ export function kindOf(policy, kind) {
65
+ return policy.kinds.find((k) => k.kind === kind);
66
+ }
67
+ /** The kinds kept in history, in declaration order. */
68
+ export function historyKinds(policy) {
69
+ return policy.kinds.filter((k) => k.history).map((k) => k.kind);
70
+ }
71
+ //# sourceMappingURL=policy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ import { type EncryptedRecord, type HeaderClass, type Parsed, type RecordKind } from "./codec.js";
2
+ import type { AuthorView } from "./epoch.js";
3
+ export interface SealedRecord {
4
+ readonly wire: Uint8Array;
5
+ readonly recordId: Uint8Array;
6
+ readonly counter: number;
7
+ readonly kind: RecordKind;
8
+ }
9
+ /** Seal one record under the active epoch. The caller persists the result and the next counter (T6). */
10
+ export declare function sealRecord(input: {
11
+ readonly streamId: Uint8Array;
12
+ readonly epoch: number;
13
+ readonly nextCounter: number;
14
+ readonly kind: RecordKind;
15
+ /** The product's event time for the record, carried in the envelope; absent when the kind has none. */
16
+ readonly eventTime?: bigint | undefined;
17
+ /** The declared header class of the kind, the one thing the relay sees of it. */
18
+ readonly headerClass: HeaderClass;
19
+ readonly payload: Uint8Array;
20
+ readonly sentAt: bigint;
21
+ readonly epochKey: Uint8Array;
22
+ readonly signingSecretKey: Uint8Array;
23
+ readonly nonce?: Uint8Array;
24
+ }): SealedRecord;
25
+ export interface OpenedRecord {
26
+ readonly record: Parsed<EncryptedRecord>;
27
+ readonly recordId: Uint8Array;
28
+ /** From the envelope: the kind, the event time if the sender gave one, and the payload. */
29
+ readonly kind: RecordKind;
30
+ readonly eventTime: bigint | undefined;
31
+ readonly payload: Uint8Array;
32
+ /** The record comes from a device of the author that is no longer current: history only. */
33
+ readonly superseded: boolean;
34
+ }
35
+ /**
36
+ * Verify and open a record. The author view supplies the certificate for the record's stream
37
+ * (the current one, or an archived one for history); `epochKeyFor` returns the stored key for
38
+ * (stream, epoch) or `undefined`, which is `KEY_PENDING`.
39
+ */
40
+ export declare function openRecordWire(wire: Uint8Array, author: AuthorView, epochKeyFor: (streamId: Uint8Array, epoch: number) => Uint8Array | undefined): OpenedRecord;
41
+ /** (generation, epoch, counter) ordering for the live pin. */
42
+ export interface PinSlot {
43
+ readonly generation: bigint;
44
+ readonly epoch: number;
45
+ readonly counter: number;
46
+ }
47
+ export declare function compareSlots(a: PinSlot, b: PinSlot): number;
48
+ export declare function slotKey(streamId: Uint8Array, epoch: number, counter: number): string;
49
+ //# sourceMappingURL=record.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"record.d.ts","sourceRoot":"","sources":["../src/record.ts"],"names":[],"mappings":"AAKA,OAAO,EAQL,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,MAAM,EACX,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AAEpB,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;CAC3B;AAED,wGAAwG;AACxG,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,uGAAuG;IACvG,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxC,iFAAiF;IACjF,QAAQ,CAAC,WAAW,EAAE,WAAW,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,gBAAgB,EAAE,UAAU,CAAC;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;CAC7B,GAAG,YAAY,CAWf;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,eAAe,CAAC,CAAC;IACzC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,OAAO,EAAE,UAAU,CAAC;IAC7B,4FAA4F;IAC5F,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;CAC9B;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,UAAU,EAClB,WAAW,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,KAAK,UAAU,GAAG,SAAS,GAC3E,YAAY,CAUd;AAED,8DAA8D;AAC9D,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,MAAM,CAI3D;AAED,wBAAgB,OAAO,CAAC,QAAQ,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAEpF"}