@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,97 @@
1
+ import { type Store, type Tx } from "../store.js";
2
+ import type { Directory, Relay, Transport } from "../transport.js";
3
+ export type CrashPhase = "beforeCommit" | "afterCommit";
4
+ export interface CrashPlan {
5
+ /** The 1-based index of the transaction (counted across every handle of the process) to crash at. */
6
+ readonly at: number;
7
+ /** Before commit: the transaction rolls back. After commit: it is durable but no caller sees the result. */
8
+ readonly phase: CrashPhase;
9
+ }
10
+ /** The process died here. Every later store call from the same process fails. */
11
+ export declare class SimulatedCrash extends Error {
12
+ readonly at: number;
13
+ readonly phase: CrashPhase;
14
+ constructor(at: number, phase: CrashPhase);
15
+ }
16
+ interface ProcessState {
17
+ transactions: number;
18
+ crashed: SimulatedCrash | undefined;
19
+ readonly plan: CrashPlan | undefined;
20
+ }
21
+ /**
22
+ * A store handle that belongs to one simulated process. All handles made with `fork()` share
23
+ * the transaction counter and die together. A read-only probe that must survive the crash reads
24
+ * the inner store directly.
25
+ */
26
+ export declare class FaultyStore implements Store {
27
+ readonly inner: Store;
28
+ private readonly forkInner?;
29
+ private readonly process;
30
+ constructor(inner: Store, plan?: CrashPlan, forkInner?: (() => Store) | undefined, process?: ProcessState);
31
+ get crashed(): SimulatedCrash | undefined;
32
+ get transactions(): number;
33
+ transaction<R>(fn: (tx: Tx) => R): Promise<R>;
34
+ read<R>(fn: (tx: Omit<Tx, "put" | "delete" | "handoff">) => R): Promise<R>;
35
+ /** Another execution context of the same process. */
36
+ fork(): FaultyStore;
37
+ private die;
38
+ private alive;
39
+ }
40
+ export type MutationName = "registerAccount" | "activateDevice" | "publishVault" | "publishOwnedCircle" | "requestJoin" | "requestLeave" | "resetAccount" | "publishEpoch" | "appendRecord" | "ackThrough";
41
+ export type ServedKind = "certificate" | "snapshot" | "vault" | "manifest" | "wrap" | "record" | "keyList" | "receipt";
42
+ export interface MaliciousKnobs {
43
+ /** Mutations whose next response is lost after the host committed it (each name is consumed once). */
44
+ readonly loseResponseOf: Set<MutationName>;
45
+ /** Mutations whose next call fails before reaching the host (each name is consumed once). */
46
+ readonly refuse: Set<MutationName>;
47
+ /** Mutations whose next response waits for the given promise after the host committed (consumed once). */
48
+ readonly hold: Map<MutationName, Promise<void>>;
49
+ /** Reads that answer "nothing" while present. */
50
+ readonly withhold: Set<"snapshots" | "epochs" | "records" | "requests" | "currentEpoch" | "keyList" | "certificates">;
51
+ /** Older documents served instead of the current ones. */
52
+ readonly replay: {
53
+ vault?: Uint8Array;
54
+ snapshots: Map<string, Uint8Array>;
55
+ keyList?: Uint8Array;
56
+ currentEpoch?: {
57
+ epoch: number;
58
+ manifestHash: Uint8Array;
59
+ };
60
+ };
61
+ /** Served documents to substitute: forks of the host's log. Keys are hex (circle id, stream id, record id). */
62
+ readonly fork: {
63
+ snapshots: Map<string, Uint8Array>;
64
+ manifests: Map<string, Uint8Array>;
65
+ records: Map<string, Uint8Array>;
66
+ certificates: Map<string, Uint8Array>;
67
+ };
68
+ /** Every record page is served twice over, and each record appears twice inside a page. */
69
+ duplicate: boolean;
70
+ /** Records inside a page are served newest first. */
71
+ reorder: boolean;
72
+ /** Flip a byte in every served document of these kinds. */
73
+ readonly tamper: Set<ServedKind>;
74
+ }
75
+ export declare function emptyKnobs(): MaliciousKnobs;
76
+ /**
77
+ * Wraps a transport. Everything not switched on passes through unchanged, so a scenario can be
78
+ * driven to a point and then attacked. `calls` records every method name in order.
79
+ */
80
+ export declare class MaliciousTransport implements Transport {
81
+ private readonly inner;
82
+ readonly knobs: MaliciousKnobs;
83
+ readonly calls: string[];
84
+ /** The mutations whose response this transport has lost so far. */
85
+ readonly losses: MutationName[];
86
+ readonly directory: Directory;
87
+ readonly relay: Relay;
88
+ constructor(inner: Transport);
89
+ private serve;
90
+ private mutate;
91
+ private wrapDirectory;
92
+ private wrapRelay;
93
+ }
94
+ /** Whether two byte strings are equal, for assertions on exact-bytes outcomes. */
95
+ export declare function sameBytes(a: Uint8Array | undefined, b: Uint8Array | undefined): boolean;
96
+ export {};
97
+ //# sourceMappingURL=faults.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faults.d.ts","sourceRoot":"","sources":["../../src/testing/faults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,264 @@
1
+ /**
2
+ * The fault harness of build step 16: a store wrapper that crashes the process at a chosen
3
+ * transaction boundary, a transport wrapper that loses responses after the host committed,
4
+ * duplicates and reorders deliveries, withholds, replays, forks and tampers with documents,
5
+ * and a sweep that runs one scenario once per boundary and checks the durable-state outcomes
6
+ * of protocol section 11 after a restart. Exported under `@plane31/blind-relay/testing` only.
7
+ */
8
+ import { equalBytes, toHex } from "../bytes.js";
9
+ import { KavachError } from "../errors.js";
10
+ import { invokeSync } from "../store.js";
11
+ /** The process died here. Every later store call from the same process fails. */
12
+ export class SimulatedCrash extends Error {
13
+ at;
14
+ phase;
15
+ constructor(at, phase) {
16
+ super(`simulated crash ${phase} transaction ${at}`);
17
+ this.at = at;
18
+ this.phase = phase;
19
+ this.name = "SimulatedCrash";
20
+ }
21
+ }
22
+ /**
23
+ * A store handle that belongs to one simulated process. All handles made with `fork()` share
24
+ * the transaction counter and die together. A read-only probe that must survive the crash reads
25
+ * the inner store directly.
26
+ */
27
+ export class FaultyStore {
28
+ inner;
29
+ forkInner;
30
+ process;
31
+ constructor(inner, plan, forkInner, process) {
32
+ this.inner = inner;
33
+ this.forkInner = forkInner;
34
+ this.process = process ?? { transactions: 0, crashed: undefined, plan };
35
+ }
36
+ get crashed() {
37
+ return this.process.crashed;
38
+ }
39
+ get transactions() {
40
+ return this.process.transactions;
41
+ }
42
+ async transaction(fn) {
43
+ this.alive();
44
+ const n = ++this.process.transactions;
45
+ const plan = this.process.plan;
46
+ const result = await this.inner.transaction((tx) => {
47
+ const r = invokeSync(fn, tx);
48
+ if (plan && plan.phase === "beforeCommit" && plan.at === n)
49
+ throw this.die(n, "beforeCommit");
50
+ return r;
51
+ });
52
+ if (plan && plan.phase === "afterCommit" && plan.at === n)
53
+ throw this.die(n, "afterCommit");
54
+ return result;
55
+ }
56
+ async read(fn) {
57
+ this.alive();
58
+ return this.inner.read(fn);
59
+ }
60
+ /** Another execution context of the same process. */
61
+ fork() {
62
+ if (!this.forkInner)
63
+ throw new Error("this store cannot fork");
64
+ return new FaultyStore(this.forkInner(), undefined, this.forkInner, this.process);
65
+ }
66
+ die(at, phase) {
67
+ this.process.crashed = new SimulatedCrash(at, phase);
68
+ return this.process.crashed;
69
+ }
70
+ alive() {
71
+ if (this.process.crashed)
72
+ throw new KavachError("STORAGE_FAILURE", "faultyStore", "the process has crashed");
73
+ }
74
+ }
75
+ export function emptyKnobs() {
76
+ return {
77
+ loseResponseOf: new Set(),
78
+ refuse: new Set(),
79
+ hold: new Map(),
80
+ withhold: new Set(),
81
+ replay: { snapshots: new Map() },
82
+ fork: { snapshots: new Map(), manifests: new Map(), records: new Map(), certificates: new Map() },
83
+ duplicate: false,
84
+ reorder: false,
85
+ tamper: new Set()
86
+ };
87
+ }
88
+ function flipByte(bytes) {
89
+ const out = Uint8Array.from(bytes);
90
+ const i = out.length - 1; // inside the signature for every signed type; inside the tag for a wrap
91
+ out[i] = (out[i] ?? 0) ^ 0x01;
92
+ return out;
93
+ }
94
+ /**
95
+ * Wraps a transport. Everything not switched on passes through unchanged, so a scenario can be
96
+ * driven to a point and then attacked. `calls` records every method name in order.
97
+ */
98
+ export class MaliciousTransport {
99
+ inner;
100
+ knobs = emptyKnobs();
101
+ calls = [];
102
+ /** The mutations whose response this transport has lost so far. */
103
+ losses = [];
104
+ directory;
105
+ relay;
106
+ constructor(inner) {
107
+ this.inner = inner;
108
+ this.directory = this.wrapDirectory();
109
+ this.relay = this.wrapRelay();
110
+ }
111
+ serve(kind, bytes) {
112
+ if (!bytes)
113
+ return bytes;
114
+ return this.knobs.tamper.has(kind) ? flipByte(bytes) : bytes;
115
+ }
116
+ async mutate(name, call) {
117
+ this.calls.push(name);
118
+ if (this.knobs.refuse.has(name)) {
119
+ this.knobs.refuse.delete(name);
120
+ throw new KavachError("NETWORK", "transport", "network unreachable");
121
+ }
122
+ const result = await call();
123
+ const gate = this.knobs.hold.get(name);
124
+ if (gate) {
125
+ this.knobs.hold.delete(name);
126
+ await gate;
127
+ }
128
+ if (this.knobs.loseResponseOf.has(name)) {
129
+ this.knobs.loseResponseOf.delete(name);
130
+ this.losses.push(name);
131
+ throw new KavachError("NETWORK", "transport", "response lost");
132
+ }
133
+ return result;
134
+ }
135
+ wrapDirectory() {
136
+ // The inner transport may rebind itself per call (a device's certificate changes at
137
+ // activation), so it is read on every call, never captured.
138
+ const d = () => this.inner.directory;
139
+ const k = this.knobs;
140
+ return {
141
+ resolveAccounts: async (names) => {
142
+ this.calls.push("resolveAccounts");
143
+ if (k.withhold.has("certificates"))
144
+ return [];
145
+ const rs = await d().resolveAccounts(names);
146
+ return rs.map((r) => ({ ...r, certificate: k.fork.certificates.get(r.accountName) ?? this.serve("certificate", r.certificate) ?? r.certificate }));
147
+ },
148
+ resolveIdentities: async (ids) => {
149
+ this.calls.push("resolveIdentities");
150
+ if (k.withhold.has("certificates"))
151
+ return [];
152
+ const rs = await d().resolveIdentities(ids);
153
+ return rs.map((r) => ({ ...r, certificate: k.fork.certificates.get(r.accountName) ?? this.serve("certificate", r.certificate) ?? r.certificate }));
154
+ },
155
+ getCertificate: async (hash) => {
156
+ this.calls.push("getCertificate");
157
+ return this.serve("certificate", await d().getCertificate(hash));
158
+ },
159
+ activateDevice: (input) => this.mutate("activateDevice", () => d().activateDevice(input)),
160
+ registerAccount: (input) => this.mutate("registerAccount", () => d().registerAccount(input)),
161
+ getVault: async (name) => {
162
+ this.calls.push("getVault");
163
+ return this.serve("vault", k.replay.vault ?? (await d().getVault(name)));
164
+ },
165
+ publishVault: (input) => this.mutate("publishVault", () => d().publishVault(input)),
166
+ getCircle: async (circleId) => {
167
+ this.calls.push("getCircle");
168
+ if (k.withhold.has("snapshots"))
169
+ return undefined;
170
+ const key = toHex(circleId);
171
+ return this.serve("snapshot", k.fork.snapshots.get(key) ?? k.replay.snapshots.get(key) ?? (await d().getCircle(circleId)));
172
+ },
173
+ publishOwnedCircle: (input) => this.mutate("publishOwnedCircle", () => d().publishOwnedCircle(input)),
174
+ requestJoin: (circleId) => this.mutate("requestJoin", () => d().requestJoin(circleId)),
175
+ requestLeave: (circleId) => this.mutate("requestLeave", () => d().requestLeave(circleId)),
176
+ readRequests: async (circleId) => {
177
+ this.calls.push("readRequests");
178
+ return k.withhold.has("requests") ? [] : d().readRequests(circleId);
179
+ },
180
+ getResetKeyList: async () => {
181
+ this.calls.push("getResetKeyList");
182
+ if (k.withhold.has("keyList"))
183
+ return undefined;
184
+ return this.serve("keyList", k.replay.keyList ?? (await d().getResetKeyList()));
185
+ },
186
+ getResetReceipt: async (id) => {
187
+ this.calls.push("getResetReceipt");
188
+ return this.serve("receipt", await d().getResetReceipt(id));
189
+ },
190
+ resetAccount: (input) => this.mutate("resetAccount", () => d().resetAccount(input))
191
+ };
192
+ }
193
+ wrapRelay() {
194
+ const r = () => this.inner.relay;
195
+ const k = this.knobs;
196
+ const pagesServed = new Map();
197
+ return {
198
+ getCurrentEpoch: async (streamId) => {
199
+ this.calls.push("getCurrentEpoch");
200
+ if (k.withhold.has("currentEpoch"))
201
+ return undefined;
202
+ return k.replay.currentEpoch ?? r().getCurrentEpoch(streamId);
203
+ },
204
+ getEpoch: async (streamId, epoch) => {
205
+ this.calls.push("getEpoch");
206
+ if (k.withhold.has("epochs"))
207
+ return undefined;
208
+ const b = await r().getEpoch(streamId, epoch);
209
+ if (!b)
210
+ return b;
211
+ const manifest = k.fork.manifests.get(`${toHex(streamId)}:${epoch}`) ?? this.serve("manifest", b.manifest) ?? b.manifest;
212
+ return { manifest, wrap: this.serve("wrap", b.wrap) };
213
+ },
214
+ publishEpoch: (input) => this.mutate("publishEpoch", () => r().publishEpoch(input)),
215
+ appendRecord: (recordId, wire) => {
216
+ // Must stay synchronous up to the inner call (T6h).
217
+ this.calls.push("appendRecord");
218
+ const p = r().appendRecord(recordId, wire);
219
+ if (!k.loseResponseOf.has("appendRecord"))
220
+ return p;
221
+ k.loseResponseOf.delete("appendRecord");
222
+ this.losses.push("appendRecord");
223
+ return p.then(() => {
224
+ throw new KavachError("NETWORK", "transport", "response lost");
225
+ });
226
+ },
227
+ readRecords: async (streamId, afterSeq, limit) => {
228
+ this.calls.push("readRecords");
229
+ if (k.withhold.has("records")) {
230
+ const probe = await r().readRecords(streamId, afterSeq, limit);
231
+ return { ...probe, records: [], nextSeq: afterSeq };
232
+ }
233
+ const page = await r().readRecords(streamId, afterSeq, limit);
234
+ let records = page.records.map((x) => {
235
+ const forked = k.fork.records.get(`${toHex(streamId)}:${x.deliverySeq}`);
236
+ return { deliverySeq: x.deliverySeq, wire: forked ?? this.serve("record", x.wire) ?? x.wire };
237
+ });
238
+ if (k.reorder)
239
+ records = [...records].reverse();
240
+ if (k.duplicate) {
241
+ records = records.flatMap((x) => [x, x]);
242
+ const key = `${toHex(streamId)}:${afterSeq}`;
243
+ const n = (pagesServed.get(key) ?? 0) + 1;
244
+ pagesServed.set(key, n);
245
+ // The first time a page is asked for, claim no progress so the reader asks again.
246
+ if (n === 1 && records.length > 0)
247
+ return { ...page, records, nextSeq: afterSeq };
248
+ }
249
+ return { ...page, records };
250
+ },
251
+ ackThrough: (streamId, cursor) => this.mutate("ackThrough", () => r().ackThrough(streamId, cursor)),
252
+ listSubscriptions: async () => {
253
+ this.calls.push("listSubscriptions");
254
+ return r().listSubscriptions();
255
+ }
256
+ };
257
+ }
258
+ }
259
+ // Helpers shared by the sweeps ----------------------------------------------------------------------
260
+ /** Whether two byte strings are equal, for assertions on exact-bytes outcomes. */
261
+ export function sameBytes(a, b) {
262
+ return a !== undefined && b !== undefined && equalBytes(a, b);
263
+ }
264
+ //# sourceMappingURL=faults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"faults.js","sourceRoot":"","sources":["../../src/testing/faults.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import { type SigningKeypair } from "../crypto.js";
2
+ export { accountKeypair, identityId } from "../crypto.js";
3
+ export { certify, deviceFromSeed, newDevice, openAccount, type DeviceKeys, type OwnAccount } from "../identity.js";
4
+ export interface TestResetKeys {
5
+ /** The deployment's management keypair, derived from a fixed seed. */
6
+ readonly management: SigningKeypair;
7
+ /** The operational keypair that signs reset receipts, derived from a fixed seed. */
8
+ readonly operational: SigningKeypair;
9
+ readonly operationalKeyId: Uint8Array;
10
+ }
11
+ /** Deterministic management and operational keys: management seed H(C("identity")), operational seed H(C("stream")), key id 07x16. */
12
+ export declare function testResetKeys(): TestResetKeys;
13
+ /** A key list of version 1, issued at `now` and valid for thirty days, signed by the management key. */
14
+ export declare function testResetKeyList(keys: TestResetKeys, now: bigint): Uint8Array;
15
+ //# sourceMappingURL=fixtures.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.d.ts","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAMA,OAAO,EAAgC,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;AAEjF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEnH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,cAAc,CAAC;IACpC,oFAAoF;IACpF,QAAQ,CAAC,WAAW,EAAE,cAAc,CAAC;IACrC,QAAQ,CAAC,gBAAgB,EAAE,UAAU,CAAC;CACvC;AAED,sIAAsI;AACtI,wBAAgB,aAAa,IAAI,aAAa,CAM7C;AAED,wGAAwG;AACxG,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,GAAG,UAAU,CAK7E"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Protocol state a test builds by hand where an application would let the client build it:
3
+ * accounts, devices and certificates for store tests, and a signed reset key list for a fake
4
+ * or real host. Call `ready()` first.
5
+ */
6
+ import { buildResetKeyList } from "../codec.js";
7
+ import { C, H, signingKeypairFromSeed } from "../crypto.js";
8
+ export { accountKeypair, identityId } from "../crypto.js";
9
+ export { certify, deviceFromSeed, newDevice, openAccount } from "../identity.js";
10
+ /** Deterministic management and operational keys: management seed H(C("identity")), operational seed H(C("stream")), key id 07x16. */
11
+ export function testResetKeys() {
12
+ return {
13
+ management: signingKeypairFromSeed(H(C("identity"))),
14
+ operational: signingKeypairFromSeed(H(C("stream"))),
15
+ operationalKeyId: new Uint8Array(16).fill(7)
16
+ };
17
+ }
18
+ /** A key list of version 1, issued at `now` and valid for thirty days, signed by the management key. */
19
+ export function testResetKeyList(keys, now) {
20
+ return buildResetKeyList({ version: 1n, issuedAt: now, expiresAt: now + 2592000000n, keys: [{ keyId: keys.operationalKeyId, publicKey: keys.operational.publicKey }] }, keys.management.secretKey);
21
+ }
22
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixtures.js","sourceRoot":"","sources":["../../src/testing/fixtures.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,CAAC,EAAE,sBAAsB,EAAuB,MAAM,cAAc,CAAC;AAEjF,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAoC,MAAM,gBAAgB,CAAC;AAUnH,sIAAsI;AACtI,MAAM,UAAU,aAAa;IAC3B,OAAO;QACL,UAAU,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QACpD,WAAW,EAAE,sBAAsB,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QACnD,gBAAgB,EAAE,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;KAC7C,CAAC;AACJ,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,gBAAgB,CAAC,IAAmB,EAAE,GAAW;IAC/D,OAAO,iBAAiB,CACtB,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,WAAc,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,EAAE,IAAI,CAAC,WAAW,CAAC,SAAS,EAAE,CAAC,EAAE,EAChJ,IAAI,CAAC,UAAU,CAAC,SAAS,CAC1B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { FakeHost, type Notification } from "./fakeHost.js";
2
+ export { testPolicy, TestClock } from "./clock.js";
3
+ export { FaultyStore, MaliciousTransport, SimulatedCrash, emptyKnobs, sameBytes, type CrashPhase, type CrashPlan, type MaliciousKnobs, type MutationName, type ServedKind } from "./faults.js";
4
+ export { MemoryPlatformProvider } from "./providers.js";
5
+ export { countBoundaries, crashSweep, hostTransport, lostResponseSweep, type DeviceName, type LostResponseRun, type SweepOptions, type SweepResult, type SweepRun, type SweepStores } from "./sweep.js";
6
+ export { accountKeypair, certify, deviceFromSeed, identityId, newDevice, openAccount, testResetKeyList, testResetKeys, type DeviceKeys, type OwnAccount, type TestResetKeys } from "./fixtures.js";
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,cAAc,EAAE,KAAK,YAAY,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC/L,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAAE,KAAK,UAAU,EAAE,KAAK,eAAe,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,KAAK,QAAQ,EAAE,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AACxM,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC"}
@@ -0,0 +1,7 @@
1
+ export { FakeHost } from "./fakeHost.js";
2
+ export { testPolicy, TestClock } from "./clock.js";
3
+ export { FaultyStore, MaliciousTransport, SimulatedCrash, emptyKnobs, sameBytes } from "./faults.js";
4
+ export { MemoryPlatformProvider } from "./providers.js";
5
+ export { countBoundaries, crashSweep, hostTransport, lostResponseSweep } from "./sweep.js";
6
+ export { accountKeypair, certify, deviceFromSeed, identityId, newDevice, openAccount, testResetKeyList, testResetKeys } from "./fixtures.js";
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/testing/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAqB,MAAM,eAAe,CAAC;AAC5D,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,kBAAkB,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAA4F,MAAM,aAAa,CAAC;AAC/L,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,aAAa,EAAE,iBAAiB,EAA+G,MAAM,YAAY,CAAC;AACxM,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAwD,MAAM,eAAe,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { ProviderLoadResult, ProviderSaveResult, ProviderStatus, ProviderStatusResult, RecoveryProvider } from "../vault.js";
2
+ /** A platform recovery provider shared by every device signed into one platform account. */
3
+ export declare class MemoryPlatformProvider implements RecoveryProvider {
4
+ private readonly platformAccount;
5
+ status_: ProviderStatus;
6
+ items: Map<string, Uint8Array>;
7
+ constructor(platformAccount: string);
8
+ private key;
9
+ load(accountName: string, identityId: Uint8Array): Promise<ProviderLoadResult>;
10
+ save(accountName: string, identityId: Uint8Array, recoveryKey: Uint8Array): Promise<ProviderSaveResult>;
11
+ status(): Promise<ProviderStatusResult>;
12
+ eraseLocalAccess(): Promise<void>;
13
+ /** Another phone on the same platform account sees the same items. */
14
+ twin(): MemoryPlatformProvider;
15
+ }
16
+ //# sourceMappingURL=providers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.d.ts","sourceRoot":"","sources":["../../src/testing/providers.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,cAAc,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAElI,4FAA4F;AAC5F,qBAAa,sBAAuB,YAAW,gBAAgB;IAIjD,OAAO,CAAC,QAAQ,CAAC,eAAe;IAH5C,OAAO,EAAE,cAAc,CAAe;IACtC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,UAAU,CAAC,CAAa;gBAEd,eAAe,EAAE,MAAM;IAEpD,OAAO,CAAC,GAAG;IAIL,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAM9E,IAAI,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAMvG,MAAM,IAAI,OAAO,CAAC,oBAAoB,CAAC;IAIvC,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAEvC,sEAAsE;IACtE,IAAI,IAAI,sBAAsB;CAK/B"}
@@ -0,0 +1,36 @@
1
+ import { toHex } from "../bytes.js";
2
+ /** A platform recovery provider shared by every device signed into one platform account. */
3
+ export class MemoryPlatformProvider {
4
+ platformAccount;
5
+ status_ = "available";
6
+ items = new Map();
7
+ constructor(platformAccount) {
8
+ this.platformAccount = platformAccount;
9
+ }
10
+ key(accountName, identityId) {
11
+ return `${this.platformAccount}:${accountName}:${toHex(identityId)}`;
12
+ }
13
+ async load(accountName, identityId) {
14
+ if (this.status_ !== "available")
15
+ return { status: this.status_ };
16
+ const k = this.items.get(this.key(accountName, identityId));
17
+ return k ? { status: "available", recoveryKey: k } : { status: "unavailable", reason: "no item" };
18
+ }
19
+ async save(accountName, identityId, recoveryKey) {
20
+ if (this.status_ !== "available")
21
+ return { status: this.status_, backupState: "unavailable" };
22
+ this.items.set(this.key(accountName, identityId), recoveryKey);
23
+ return { status: "available", backupState: "pending" };
24
+ }
25
+ async status() {
26
+ return { status: this.status_, backupState: this.status_ === "available" ? "pending" : "unavailable" };
27
+ }
28
+ async eraseLocalAccess() { }
29
+ /** Another phone on the same platform account sees the same items. */
30
+ twin() {
31
+ const p = new MemoryPlatformProvider(this.platformAccount);
32
+ p.items = this.items;
33
+ return p;
34
+ }
35
+ }
36
+ //# sourceMappingURL=providers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"providers.js","sourceRoot":"","sources":["../../src/testing/providers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAGpC,4FAA4F;AAC5F,MAAM,OAAO,sBAAsB;IAIJ;IAH7B,OAAO,GAAmB,WAAW,CAAC;IACtC,KAAK,GAA4B,IAAI,GAAG,EAAE,CAAC;IAE3C,YAA6B,eAAuB;QAAvB,oBAAe,GAAf,eAAe,CAAQ;IAAG,CAAC;IAEhD,GAAG,CAAC,WAAmB,EAAE,UAAsB;QACrD,OAAO,GAAG,IAAI,CAAC,eAAe,IAAI,WAAW,IAAI,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAmB,EAAE,UAAsB;QACpD,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW;YAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC;QAClE,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC,CAAC;QAC5D,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,CAAC;IACpG,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,WAAmB,EAAE,UAAsB,EAAE,WAAuB;QAC7E,IAAI,IAAI,CAAC,OAAO,KAAK,WAAW;YAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,CAAC;QAC9F,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,EAAE,WAAW,CAAC,CAAC;QAC/D,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,MAAM;QACV,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,CAAC,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACzG,CAAC;IAED,KAAK,CAAC,gBAAgB,KAAmB,CAAC;IAE1C,sEAAsE;IACtE,IAAI;QACF,MAAM,CAAC,GAAG,IAAI,sBAAsB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAC3D,CAAC,CAAC,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;QACrB,OAAO,CAAC,CAAC;IACX,CAAC;CACF"}
@@ -0,0 +1,46 @@
1
+ import { type Store } from "../store.js";
2
+ import type { Transport } from "../transport.js";
3
+ import { FakeHost } from "./fakeHost.js";
4
+ import { type CrashPhase, type MutationName } from "./faults.js";
5
+ export type DeviceName = "alice" | "bob" | "bob2";
6
+ export interface SweepStores {
7
+ /** A durable store for the named device of this run, empty. */
8
+ open(run: string, name: DeviceName): Promise<Store> | Store;
9
+ /** The same durable state as a restarted process opens it: a new handle on the same file. */
10
+ reopen(run: string, name: DeviceName): Promise<Store> | Store;
11
+ /** Another in-process handle on the same durable state, when the engine can give one. */
12
+ fork?(run: string, name: DeviceName): Store;
13
+ dispose?(run: string): Promise<void> | void;
14
+ }
15
+ export interface SweepOptions {
16
+ readonly stores: SweepStores;
17
+ readonly victim: DeviceName;
18
+ readonly phases?: readonly CrashPhase[];
19
+ /** Run only these boundaries (for narrowing a failure). */
20
+ readonly only?: readonly number[];
21
+ }
22
+ export interface SweepRun {
23
+ readonly at: number;
24
+ readonly phase: CrashPhase;
25
+ /** The scenario step during which the process died. */
26
+ readonly crashedDuring: string;
27
+ /** What the re-invoked step answered after the restart. */
28
+ readonly retry: string;
29
+ }
30
+ export interface SweepResult {
31
+ readonly boundaries: number;
32
+ readonly runs: readonly SweepRun[];
33
+ }
34
+ export interface LostResponseRun {
35
+ readonly mutation: MutationName;
36
+ /** Whether the victim actually issued that mutation in this scenario. */
37
+ readonly exercised: boolean;
38
+ }
39
+ /** The transport of a device: bound to the account's current certificate at the host on every call. */
40
+ export declare function hostTransport(host: FakeHost, account: string): Transport;
41
+ /** Runs the scenario with no fault and returns the victim's transaction count. */
42
+ export declare function countBoundaries(stores: SweepStores, victim: DeviceName): Promise<number>;
43
+ export declare function crashSweep(options: SweepOptions): Promise<SweepResult>;
44
+ /** For each mutation the victim issues, the host commits it and the response is lost once. */
45
+ export declare function lostResponseSweep(stores: SweepStores, victim: DeviceName): Promise<LostResponseRun[]>;
46
+ //# sourceMappingURL=sweep.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweep.d.ts","sourceRoot":"","sources":["../../src/testing/sweep.ts"],"names":[],"mappings":"AAUA,OAAO,EAAqB,KAAK,KAAK,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAmC,KAAK,UAAU,EAAkB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAIlH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,KAAK,GAAG,MAAM,CAAC;AAElD,MAAM,WAAW,WAAW;IAC1B,+DAA+D;IAC/D,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IAC5D,6FAA6F;IAC7F,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IAC9D,yFAAyF;IACzF,IAAI,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,GAAG,KAAK,CAAC;IAC5C,OAAO,CAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;CAC7C;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,2DAA2D;IAC3D,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACnC;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,uDAAuD;IACvD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,2DAA2D;IAC3D,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,yEAAyE;IACzE,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC;CAC7B;AAkCD,uGAAuG;AACvG,wBAAgB,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,SAAS,CAaxE;AAuPD,kFAAkF;AAClF,wBAAsB,eAAe,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAY9F;AAED,wBAAsB,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAoB5E;AAID,8FAA8F;AAC9F,wBAAsB,iBAAiB,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC,CAe3G"}