agent-comms 8.6.2 → 8.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (183) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +27 -1
  4. package/dist/account-cli.d.ts +34 -0
  5. package/dist/account-cli.d.ts.map +1 -0
  6. package/dist/account-cli.js +140 -0
  7. package/dist/account-cli.js.map +1 -0
  8. package/dist/account-join-cli.d.ts +17 -0
  9. package/dist/account-join-cli.d.ts.map +1 -0
  10. package/dist/account-join-cli.js +140 -0
  11. package/dist/account-join-cli.js.map +1 -0
  12. package/dist/bridges/mcp/server.d.ts +1 -4
  13. package/dist/bridges/mcp/server.d.ts.map +1 -1
  14. package/dist/bridges/mcp/server.js +1 -1
  15. package/dist/bridges/mcp/server.js.map +1 -1
  16. package/dist/cli.d.ts +4 -0
  17. package/dist/cli.d.ts.map +1 -1
  18. package/dist/cli.js +24 -1
  19. package/dist/cli.js.map +1 -1
  20. package/dist/core/account-bundle.d.ts +22 -0
  21. package/dist/core/account-bundle.d.ts.map +1 -0
  22. package/dist/core/account-bundle.js +143 -0
  23. package/dist/core/account-bundle.js.map +1 -0
  24. package/dist/core/account-join.d.ts +62 -0
  25. package/dist/core/account-join.d.ts.map +1 -0
  26. package/dist/core/account-join.js +150 -0
  27. package/dist/core/account-join.js.map +1 -0
  28. package/dist/core/account-ledger-crypto.d.ts +28 -0
  29. package/dist/core/account-ledger-crypto.d.ts.map +1 -0
  30. package/dist/core/account-ledger-crypto.js +101 -0
  31. package/dist/core/account-ledger-crypto.js.map +1 -0
  32. package/dist/core/account-ledger-store.d.ts +21 -0
  33. package/dist/core/account-ledger-store.d.ts.map +1 -0
  34. package/dist/core/account-ledger-store.js +34 -0
  35. package/dist/core/account-ledger-store.js.map +1 -0
  36. package/dist/core/account-ledger.d.ts +80 -0
  37. package/dist/core/account-ledger.d.ts.map +1 -0
  38. package/dist/core/account-ledger.js +247 -0
  39. package/dist/core/account-ledger.js.map +1 -0
  40. package/dist/core/bridge-mesh.d.ts.map +1 -1
  41. package/dist/core/bridge-mesh.js +12 -1
  42. package/dist/core/bridge-mesh.js.map +1 -1
  43. package/dist/core/data-frame-routing.d.ts +50 -3
  44. package/dist/core/data-frame-routing.d.ts.map +1 -1
  45. package/dist/core/data-frame-routing.js +112 -5
  46. package/dist/core/data-frame-routing.js.map +1 -1
  47. package/dist/core/device-membership.d.ts +8 -8
  48. package/dist/core/device-membership.d.ts.map +1 -1
  49. package/dist/core/device-membership.js +17 -16
  50. package/dist/core/device-membership.js.map +1 -1
  51. package/dist/core/dm-send-delegation.d.ts +4 -4
  52. package/dist/core/dm-send-delegation.d.ts.map +1 -1
  53. package/dist/core/dm-send-delegation.js +2 -3
  54. package/dist/core/dm-send-delegation.js.map +1 -1
  55. package/dist/core/group-proofs.d.ts +5 -0
  56. package/dist/core/group-proofs.d.ts.map +1 -1
  57. package/dist/core/group-proofs.js +4 -0
  58. package/dist/core/group-proofs.js.map +1 -1
  59. package/dist/core/identity-store.d.ts.map +1 -1
  60. package/dist/core/identity-store.js +2 -62
  61. package/dist/core/identity-store.js.map +1 -1
  62. package/dist/core/issuer-identity-file.d.ts +4 -0
  63. package/dist/core/issuer-identity-file.d.ts.map +1 -1
  64. package/dist/core/issuer-identity-file.js +7 -5
  65. package/dist/core/issuer-identity-file.js.map +1 -1
  66. package/dist/core/ledger-lock.d.ts +12 -0
  67. package/dist/core/ledger-lock.d.ts.map +1 -0
  68. package/dist/core/ledger-lock.js +62 -0
  69. package/dist/core/ledger-lock.js.map +1 -0
  70. package/dist/core/membership-proofs.d.ts +7 -0
  71. package/dist/core/membership-proofs.d.ts.map +1 -1
  72. package/dist/core/membership-proofs.js +26 -1
  73. package/dist/core/membership-proofs.js.map +1 -1
  74. package/dist/core/mesh-store-shared.d.ts +4 -1
  75. package/dist/core/mesh-store-shared.d.ts.map +1 -1
  76. package/dist/core/mesh-store-shared.js.map +1 -1
  77. package/dist/core/mesh-store.d.ts +17 -8
  78. package/dist/core/mesh-store.d.ts.map +1 -1
  79. package/dist/core/mesh-store.js +41 -41
  80. package/dist/core/mesh-store.js.map +1 -1
  81. package/dist/core/peer-versions.d.ts +11 -0
  82. package/dist/core/peer-versions.d.ts.map +1 -1
  83. package/dist/core/peer-versions.js +9 -0
  84. package/dist/core/peer-versions.js.map +1 -1
  85. package/dist/core/pid-lock-file.d.ts +20 -0
  86. package/dist/core/pid-lock-file.d.ts.map +1 -0
  87. package/dist/core/pid-lock-file.js +115 -0
  88. package/dist/core/pid-lock-file.js.map +1 -0
  89. package/dist/core/room-lifecycle.d.ts +2 -2
  90. package/dist/core/room-lifecycle.d.ts.map +1 -1
  91. package/dist/core/room-lifecycle.js +18 -19
  92. package/dist/core/room-lifecycle.js.map +1 -1
  93. package/dist/core/transport-queries.d.ts +11 -0
  94. package/dist/core/transport-queries.d.ts.map +1 -0
  95. package/dist/core/transport-queries.js +30 -0
  96. package/dist/core/transport-queries.js.map +1 -0
  97. package/dist/core/user-identity.d.ts +23 -18
  98. package/dist/core/user-identity.d.ts.map +1 -1
  99. package/dist/core/user-identity.js +99 -61
  100. package/dist/core/user-identity.js.map +1 -1
  101. package/dist/core/wire-mesh-transport-options.d.ts +11 -2
  102. package/dist/core/wire-mesh-transport-options.d.ts.map +1 -1
  103. package/dist/core/wire-mesh-transport-options.js.map +1 -1
  104. package/dist/core/wire-mesh-transport.d.ts +4 -6
  105. package/dist/core/wire-mesh-transport.d.ts.map +1 -1
  106. package/dist/core/wire-mesh-transport.js +16 -20
  107. package/dist/core/wire-mesh-transport.js.map +1 -1
  108. package/dist/test/account-join.integration.test.d.ts +5 -0
  109. package/dist/test/account-join.integration.test.d.ts.map +1 -0
  110. package/dist/test/account-join.integration.test.js +183 -0
  111. package/dist/test/account-join.integration.test.js.map +1 -0
  112. package/dist/test/account-ledger-lock-worker.d.ts +9 -0
  113. package/dist/test/account-ledger-lock-worker.d.ts.map +1 -0
  114. package/dist/test/account-ledger-lock-worker.js +34 -0
  115. package/dist/test/account-ledger-lock-worker.js.map +1 -0
  116. package/dist/test/account-ledger-lock.integration.test.d.ts +5 -0
  117. package/dist/test/account-ledger-lock.integration.test.d.ts.map +1 -0
  118. package/dist/test/account-ledger-lock.integration.test.js +71 -0
  119. package/dist/test/account-ledger-lock.integration.test.js.map +1 -0
  120. package/dist/test/account-ledger-replication.integration.test.d.ts +5 -0
  121. package/dist/test/account-ledger-replication.integration.test.d.ts.map +1 -0
  122. package/dist/test/account-ledger-replication.integration.test.js +145 -0
  123. package/dist/test/account-ledger-replication.integration.test.js.map +1 -0
  124. package/dist/test/account-ledger.unit.test.d.ts +5 -0
  125. package/dist/test/account-ledger.unit.test.d.ts.map +1 -0
  126. package/dist/test/account-ledger.unit.test.js +317 -0
  127. package/dist/test/account-ledger.unit.test.js.map +1 -0
  128. package/dist/test/account-transfer.unit.test.d.ts +5 -0
  129. package/dist/test/account-transfer.unit.test.d.ts.map +1 -0
  130. package/dist/test/account-transfer.unit.test.js +204 -0
  131. package/dist/test/account-transfer.unit.test.js.map +1 -0
  132. package/dist/test/delivery-engine-delivery.unit.test.js +1 -0
  133. package/dist/test/delivery-engine-delivery.unit.test.js.map +1 -1
  134. package/dist/test/delivery-engine-directed-notify.unit.test.js +1 -0
  135. package/dist/test/delivery-engine-directed-notify.unit.test.js.map +1 -1
  136. package/dist/test/delivery-engine-own-agent.unit.test.js +1 -0
  137. package/dist/test/delivery-engine-own-agent.unit.test.js.map +1 -1
  138. package/dist/test/delivery-engine.unit.test.js +1 -0
  139. package/dist/test/delivery-engine.unit.test.js.map +1 -1
  140. package/dist/test/device-membership.unit.test.js +81 -30
  141. package/dist/test/device-membership.unit.test.js.map +1 -1
  142. package/dist/test/dm-send-delegation.unit.test.js +25 -14
  143. package/dist/test/dm-send-delegation.unit.test.js.map +1 -1
  144. package/dist/test/dm-send-principal-delegation.integration.test.js +9 -2
  145. package/dist/test/dm-send-principal-delegation.integration.test.js.map +1 -1
  146. package/dist/test/hidden-line.unit.test.d.ts +5 -0
  147. package/dist/test/hidden-line.unit.test.d.ts.map +1 -0
  148. package/dist/test/hidden-line.unit.test.js +40 -0
  149. package/dist/test/hidden-line.unit.test.js.map +1 -0
  150. package/dist/test/identity-restart.integration.test.js +8 -1
  151. package/dist/test/identity-restart.integration.test.js.map +1 -1
  152. package/dist/test/mcp-stdout-channel.integration.test.js +2 -2
  153. package/dist/test/mcp-stdout-channel.integration.test.js.map +1 -1
  154. package/dist/test/mesh-smoke.runner.js +2 -1
  155. package/dist/test/mesh-smoke.runner.js.map +1 -1
  156. package/dist/test/room-join-admission.integration.test.js +8 -1
  157. package/dist/test/room-join-admission.integration.test.js.map +1 -1
  158. package/dist/test/room-lifecycle-bare-name.unit.test.js +1 -0
  159. package/dist/test/room-lifecycle-bare-name.unit.test.js.map +1 -1
  160. package/dist/test/room-lifecycle-membership.unit.test.js +1 -0
  161. package/dist/test/room-lifecycle-membership.unit.test.js.map +1 -1
  162. package/dist/test/room-lifecycle-remote.unit.test.js +1 -0
  163. package/dist/test/room-lifecycle-remote.unit.test.js.map +1 -1
  164. package/dist/test/room-lifecycle.unit.test.js +1 -0
  165. package/dist/test/room-lifecycle.unit.test.js.map +1 -1
  166. package/dist/test/room-messaging-durable-send.unit.test.js +1 -0
  167. package/dist/test/room-messaging-durable-send.unit.test.js.map +1 -1
  168. package/dist/test/room-messaging.unit.test.js +1 -0
  169. package/dist/test/room-messaging.unit.test.js.map +1 -1
  170. package/dist/test/room-protocol-notify.unit.test.js +1 -0
  171. package/dist/test/room-protocol-notify.unit.test.js.map +1 -1
  172. package/dist/test/room-protocol.helper.d.ts.map +1 -1
  173. package/dist/test/room-protocol.helper.js +1 -0
  174. package/dist/test/room-protocol.helper.js.map +1 -1
  175. package/dist/test/room-send-retry.integration.test.js +8 -1
  176. package/dist/test/room-send-retry.integration.test.js.map +1 -1
  177. package/dist/test/test-transport.d.ts +9 -0
  178. package/dist/test/test-transport.d.ts.map +1 -1
  179. package/dist/test/test-transport.js +14 -5
  180. package/dist/test/test-transport.js.map +1 -1
  181. package/dist/test/user-identity.unit.test.js +75 -106
  182. package/dist/test/user-identity.unit.test.js.map +1 -1
  183. package/package.json +1 -1
@@ -0,0 +1,145 @@
1
+ /**
2
+ * Integration tests for the account's replicated grant ledger over a real mesh (agent-comms#344): two machines holding the same account key, each with its own user-identity.json and ledger store, connected directly. A grant minted on one reaches the other by data-domain fan-out, and the other can then revoke it, which a machine-local ledger could never do.
3
+ */
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { tmpdir } from "node:os";
7
+ import { afterEach, describe, expect, it } from "vitest";
8
+ import { createMemoryStorage } from "wire-mesh-core/adapters/memory-storage";
9
+ import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
10
+ import { createRevocationView, } from "wire-mesh-core/domain/revocation-view";
11
+ import { MeshStore } from "../core/mesh-store.js";
12
+ import { openAccountLedger } from "../core/account-ledger-store.js";
13
+ import { generateIdentity } from "../core/identity.js";
14
+ import { loadOrCreateUserIdentity } from "../core/user-identity.js";
15
+ import { deviceIdToHex } from "wire-mesh-core/domain/device-id";
16
+ import { freeLocalPort, TeardownStack } from "./hub-helpers.js";
17
+ import { waitFor, wireTestTransportWithHub } from "./test-transport.js";
18
+ /** Short enough that the ledger's announcement round, which rides the re-advertise cadence, fires many times within a test's wait budget. */
19
+ const FAST_GOSSIP_INTERVAL_MS = 50;
20
+ const cleanups = new TeardownStack();
21
+ const dirs = [];
22
+ afterEach(async () => {
23
+ await cleanups.run();
24
+ for (const dir of dirs.splice(0)) {
25
+ fs.rmSync(dir, { recursive: true, force: true });
26
+ }
27
+ });
28
+ function userDir() {
29
+ const dir = fs.mkdtempSync(path.join(tmpdir(), "ledger-replication-user-"));
30
+ dirs.push(dir);
31
+ return dir;
32
+ }
33
+ /** Gives `toDir` a copy of the account key in `fromDir` and nothing else, as a deliberate copy of the key to a second machine would. */
34
+ function copyAccountKey(fromDir, toDir) {
35
+ const parsed = JSON.parse(fs.readFileSync(path.join(fromDir, "user-identity.json"), "utf-8"));
36
+ if (typeof parsed !== "object" ||
37
+ parsed === null ||
38
+ !("privateKey" in parsed) ||
39
+ !("certificate" in parsed) ||
40
+ !("expiresAt" in parsed)) {
41
+ throw new Error("user-identity.json has no key material");
42
+ }
43
+ const { privateKey, certificate, expiresAt } = parsed;
44
+ fs.writeFileSync(path.join(toDir, "user-identity.json"), JSON.stringify({ privateKey, certificate, expiresAt }), { mode: 0o600 });
45
+ }
46
+ async function machine(coordinatorPort, userIdentityDir, name) {
47
+ const store = new MeshStore({ coordinatorPort });
48
+ const revocation = createRevocationView();
49
+ const dataStorage = createMemoryStorage();
50
+ const { transport } = await wireTestTransportWithHub(store, {
51
+ presenceReadvertiseIntervalMs: FAST_GOSSIP_INTERVAL_MS,
52
+ userIdentityOptions: { dir: userIdentityDir },
53
+ revocation,
54
+ dataStorage,
55
+ });
56
+ await store.init();
57
+ cleanups.push(async () => store.shutdown());
58
+ // A visible agent's advert carries its device's membership proof, which is how the other machine recognises it as holding the same account and offers it the ledger.
59
+ await store.registerAgent({
60
+ name,
61
+ harness: "test",
62
+ cwd: `/test/${name}`,
63
+ pid: process.pid,
64
+ visibility: "visible",
65
+ tags: [],
66
+ });
67
+ return { store, transport, revocation, dataStorage };
68
+ }
69
+ /** Another handle on a machine's ledger store, the way a second bridge on that machine would open it. */
70
+ async function ledgerOn(dir) {
71
+ return openAccountLedger({
72
+ userIdentityOptions: { dir },
73
+ userIdentity: loadOrCreateUserIdentity({ dir }),
74
+ clock: createSystemClock(),
75
+ });
76
+ }
77
+ async function outstandingDm(ledger, bearer) {
78
+ const grants = await ledger.outstandingGrants("dm", bearer);
79
+ return grants.map((grant) => Buffer.from(grant.tokenId).toString("hex"));
80
+ }
81
+ describe("account ledger replication", () => {
82
+ it("revokes on a second machine a DM grant minted on the first", async () => {
83
+ const port = await freeLocalPort();
84
+ const dirA = userDir();
85
+ const dirB = userDir();
86
+ loadOrCreateUserIdentity({ dir: dirA });
87
+ copyAccountKey(dirA, dirB);
88
+ const { store: a } = await machine(port, dirA, "machine-a");
89
+ const { store: b } = await machine(port, dirB, "machine-b");
90
+ expect(b.getUserPrincipalId()).toBe(a.getUserPrincipalId());
91
+ const bearer = deviceIdToHex(Uint8Array.from(generateIdentity().deviceId));
92
+ await a.admitAgentForDm(bearer);
93
+ const ledgerA = await ledgerOn(dirA);
94
+ const ledgerB = await ledgerOn(dirB);
95
+ const [minted] = await outstandingDm(ledgerA, bearer);
96
+ if (minted === undefined)
97
+ throw new Error("expected A to record its grant");
98
+ await waitFor(async () => (await outstandingDm(ledgerB, bearer)).includes(minted), "B's ledger to hold the grant A minted");
99
+ await b.revokeAgentDmAccess(bearer);
100
+ expect(await outstandingDm(ledgerB, bearer)).toEqual([]);
101
+ await waitFor(async () => (await outstandingDm(ledgerA, bearer)).length === 0, "A's ledger to learn B's revocation");
102
+ expect(await ledgerA.revocations()).toHaveLength(1);
103
+ });
104
+ it("teaches a machine a revocation made on another through the replicated ledger alone", async () => {
105
+ const port = await freeLocalPort();
106
+ const dirA = userDir();
107
+ const dirB = userDir();
108
+ loadOrCreateUserIdentity({ dir: dirA });
109
+ copyAccountKey(dirA, dirB);
110
+ const a = await machine(port, dirA, "machine-a");
111
+ const b = await machine(port, dirB, "machine-b");
112
+ const bearer = deviceIdToHex(Uint8Array.from(generateIdentity().deviceId));
113
+ // The gossiped revocation-announce never leaves B, so the only way A can learn of the revocation is B's writer log.
114
+ b.transport.broadcastRevocation = async () => { };
115
+ await a.store.admitAgentForDm(bearer);
116
+ const ledgerB = await ledgerOn(dirB);
117
+ await waitFor(async () => (await outstandingDm(ledgerB, bearer)).length === 1, "B's ledger to hold the grant A minted");
118
+ const [minted] = await ledgerB.outstandingGrants("dm", bearer);
119
+ if (minted === undefined)
120
+ throw new Error("expected the minted grant");
121
+ await b.store.revokeAgentDmAccess(bearer);
122
+ await waitFor(async () => (await a.revocation.entriesFor(minted.tokenId)).length > 0, "A's RevocationView to refuse the grant B revoked");
123
+ });
124
+ it("never offers the ledger to a device of another account", async () => {
125
+ const port = await freeLocalPort();
126
+ const dirA = userDir();
127
+ const dirB = userDir();
128
+ const dirOther = userDir();
129
+ loadOrCreateUserIdentity({ dir: dirA });
130
+ copyAccountKey(dirA, dirB);
131
+ const a = await machine(port, dirA, "machine-a");
132
+ const b = await machine(port, dirB, "machine-b");
133
+ const other = await machine(port, dirOther, "other-account");
134
+ const bearer = deviceIdToHex(Uint8Array.from(generateIdentity().deviceId));
135
+ await a.store.admitAgentForDm(bearer);
136
+ const ledgerB = await ledgerOn(dirB);
137
+ await waitFor(async () => (await outstandingDm(ledgerB, bearer)).length === 1, "B's ledger to hold the grant A minted");
138
+ const [writerLog] = await (await ledgerOn(dirA)).announcements();
139
+ if (writerLog === undefined)
140
+ throw new Error("expected A's writer log");
141
+ // Every announcement round that reached B also passed the other account's device, so by now it would have asked for and stored the log if it had been offered.
142
+ expect(await other.dataStorage.keys(`data/${deviceIdToHex(writerLog.peer)}/`)).toEqual([]);
143
+ });
144
+ });
145
+ //# sourceMappingURL=account-ledger-replication.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-ledger-replication.integration.test.js","sourceRoot":"","sources":["../../src/test/account-ledger-replication.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Unit tests for the account's replicated grant ledger (agent-comms#344): its sealing and writer-log recognition, replication between two machines holding the same account key by plain data-domain frame exchange, revocation from a machine other than the one that minted the grant, and migration of a pre-ledger user-identity.json.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=account-ledger.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-ledger.unit.test.d.ts","sourceRoot":"","sources":["../../src/test/account-ledger.unit.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -0,0 +1,317 @@
1
+ /**
2
+ * Unit tests for the account's replicated grant ledger (agent-comms#344): its sealing and writer-log recognition, replication between two machines holding the same account key by plain data-domain frame exchange, revocation from a machine other than the one that minted the grant, and migration of a pre-ledger user-identity.json.
3
+ */
4
+ import * as fs from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import path from "node:path";
7
+ import { describe, expect, it } from "vitest";
8
+ import { createMemoryStorage } from "wire-mesh-core/adapters/memory-storage";
9
+ import { createNodeFsStorage } from "wire-mesh-core/adapters/node-fs-storage";
10
+ import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
11
+ import { mintRevocationEntry } from "wire-mesh-core/domain/tokens";
12
+ import { deriveAccountLedgerKeys, generateWriterNonce, isWriterLogId, openLedgerEntry, sealLedgerEntry, writerLogId, } from "../core/account-ledger-crypto.js";
13
+ import { AccountLedger } from "../core/account-ledger.js";
14
+ import { openAccountLedger } from "../core/account-ledger-store.js";
15
+ import { generateIdentity } from "../core/identity.js";
16
+ import { createFileLedgerLock, createInProcessLedgerLock, } from "../core/ledger-lock.js";
17
+ import { randomId } from "../core/random-id.js";
18
+ import { loadOrCreateUserIdentity, readLegacyIssuedGrants, } from "../core/user-identity.js";
19
+ import { toIdentityPort } from "../core/wire-mesh-identity.js";
20
+ /** Enough appends in flight at once that two unserialised writers would all but certainly read the same head at least once. */
21
+ const CONCURRENT_APPENDS = 8;
22
+ /** One machine's copy of an account's ledger: its own storage and writer nonce, the account key it shares with every other machine of the account. */
23
+ function machineLedger(account) {
24
+ return new AccountLedger({
25
+ accountPrivateKey: account.privateKey,
26
+ writerNonce: generateWriterNonce(),
27
+ storage: createMemoryStorage(),
28
+ lock: createInProcessLedgerLock(),
29
+ clock: createSystemClock(),
30
+ });
31
+ }
32
+ /** Wraps `inner` so a test can stop a data log's head write half-way, the way a filesystem write that truncates and then writes can be caught between the two by a reader in another process: the head is left empty until the test releases it. */
33
+ function pausingHeadWrites(inner) {
34
+ let pending;
35
+ const storage = {
36
+ get: async (key) => inner.get(key),
37
+ delete: async (key) => inner.delete(key),
38
+ keys: async (prefix) => inner.keys(prefix),
39
+ set: async (key, value) => {
40
+ const pause = key.endsWith("/head") ? pending : undefined;
41
+ if (pause !== undefined) {
42
+ pending = undefined;
43
+ await inner.set(key, new Uint8Array());
44
+ pause.arrive();
45
+ await pause.released;
46
+ }
47
+ await inner.set(key, value);
48
+ },
49
+ };
50
+ return {
51
+ storage,
52
+ pauseNextHeadWrite: () => {
53
+ const reached = Promise.withResolvers();
54
+ const released = Promise.withResolvers();
55
+ pending = {
56
+ arrive: () => {
57
+ reached.resolve(undefined);
58
+ },
59
+ released: released.promise,
60
+ };
61
+ return {
62
+ reached: reached.promise,
63
+ release: () => {
64
+ released.resolve(undefined);
65
+ },
66
+ };
67
+ },
68
+ };
69
+ }
70
+ /** Runs the data-domain exchange a transport would between two connected machines until `to` holds everything `from` offers: have, then request and entries until caught up. */
71
+ async function replicate(from, to) {
72
+ for (const have of await from.announcements()) {
73
+ let next = await to.handleDataFrame(have);
74
+ while (next !== null && next.type === "data-request") {
75
+ const entries = await from.handleDataFrame(next);
76
+ if (entries === null)
77
+ break;
78
+ await to.handleDataFrame(entries);
79
+ next = await to.handleDataFrame(have);
80
+ }
81
+ }
82
+ }
83
+ async function tokenIds(ledger, kind, subject) {
84
+ const grants = await ledger.outstandingGrants(kind, subject);
85
+ return grants.map((grant) => grant.tokenId);
86
+ }
87
+ describe("account ledger sealing", () => {
88
+ const account = generateIdentity();
89
+ const keys = deriveAccountLedgerKeys(account.privateKey);
90
+ const log = writerLogId(keys, generateWriterNonce());
91
+ const plaintext = randomId();
92
+ it("opens an entry sealed for the same log and position", () => {
93
+ const sealed = sealLedgerEntry(keys, log, 1, plaintext);
94
+ expect(openLedgerEntry(keys, log, 1, sealed)).toEqual(plaintext);
95
+ });
96
+ it("does not open an entry moved to another position, another log, or under another account", () => {
97
+ const sealed = sealLedgerEntry(keys, log, 1, plaintext);
98
+ const otherLog = writerLogId(keys, generateWriterNonce());
99
+ const otherKeys = deriveAccountLedgerKeys(generateIdentity().privateKey);
100
+ expect(openLedgerEntry(keys, log, 2, sealed)).toBeUndefined();
101
+ expect(openLedgerEntry(keys, otherLog, 1, sealed)).toBeUndefined();
102
+ expect(openLedgerEntry(otherKeys, log, 1, sealed)).toBeUndefined();
103
+ });
104
+ it("recognises its own writer logs and nothing else", () => {
105
+ const otherKeys = deriveAccountLedgerKeys(generateIdentity().privateKey);
106
+ expect(isWriterLogId(keys, log)).toBe(true);
107
+ expect(isWriterLogId(otherKeys, log)).toBe(false);
108
+ expect(isWriterLogId(keys, randomId())).toBe(false);
109
+ });
110
+ it("derives the same keys from every copy of the account key", () => {
111
+ const copy = deriveAccountLedgerKeys(account.privateKey);
112
+ const sealed = sealLedgerEntry(keys, log, 1, plaintext);
113
+ expect(openLedgerEntry(copy, log, 1, sealed)).toEqual(plaintext);
114
+ });
115
+ });
116
+ describe("account ledger replication", () => {
117
+ it("lets a second machine holding the account key revoke a grant the first minted", async () => {
118
+ const account = generateIdentity();
119
+ const accountPort = await toIdentityPort(account);
120
+ const first = machineLedger(account);
121
+ const second = machineLedger(account);
122
+ const tokenId = randomId();
123
+ await first.recordGrant("device", "device-a", tokenId);
124
+ await replicate(first, second);
125
+ expect(await tokenIds(second, "device", "device-a")).toEqual([tokenId]);
126
+ const revocation = await mintRevocationEntry({
127
+ identity: accountPort,
128
+ tokenId,
129
+ revokedAt: Date.now(),
130
+ });
131
+ await second.recordRevocation("device", "device-a", tokenId, revocation);
132
+ const learned = [];
133
+ first.onReplicatedRevocation((entry) => {
134
+ learned.push(entry);
135
+ });
136
+ await replicate(second, first);
137
+ expect(await tokenIds(first, "device", "device-a")).toEqual([]);
138
+ expect(learned).toEqual([revocation]);
139
+ expect(await first.revocations()).toEqual([revocation]);
140
+ });
141
+ it("keeps both machines' grants when each appends while apart", async () => {
142
+ const account = generateIdentity();
143
+ const first = machineLedger(account);
144
+ const second = machineLedger(account);
145
+ const fromFirst = randomId();
146
+ const fromSecond = randomId();
147
+ await first.recordGrant("dm", "bearer", fromFirst);
148
+ await second.recordGrant("dm", "bearer", fromSecond);
149
+ await replicate(first, second);
150
+ await replicate(second, first);
151
+ for (const ledger of [first, second]) {
152
+ expect(await tokenIds(ledger, "dm", "bearer")).toEqual(expect.arrayContaining([fromFirst, fromSecond]));
153
+ expect(await tokenIds(ledger, "dm", "bearer")).toHaveLength(2);
154
+ }
155
+ });
156
+ it("refuses entries for one of its writer logs that were not sealed under the account key", async () => {
157
+ const account = generateIdentity();
158
+ const ledger = machineLedger(account);
159
+ const keys = deriveAccountLedgerKeys(account.privateKey);
160
+ const log = writerLogId(keys, generateWriterNonce());
161
+ const forged = sealLedgerEntry(deriveAccountLedgerKeys(generateIdentity().privateKey), log, 1, Uint8Array.from([0]));
162
+ await ledger.handleDataFrame({
163
+ type: "data-entries",
164
+ peer: log,
165
+ "from-seq": 0,
166
+ entries: [forged],
167
+ });
168
+ expect(ledger.ownsLog(log)).toBe(true);
169
+ expect(await ledger.announcements()).toEqual([]);
170
+ });
171
+ it("gives no reading to a machine without the account key", async () => {
172
+ const account = generateIdentity();
173
+ const ledger = machineLedger(account);
174
+ const stranger = machineLedger(generateIdentity());
175
+ await ledger.recordGrant("device", "device-a", randomId());
176
+ const [have] = await ledger.announcements();
177
+ if (have === undefined)
178
+ throw new Error("expected an announcement");
179
+ expect(stranger.ownsLog(have.peer)).toBe(false);
180
+ });
181
+ it("never misses a replicated grant while another bridge on the machine is storing that log", async () => {
182
+ const account = generateIdentity();
183
+ const origin = machineLedger(account);
184
+ const dir = fs.mkdtempSync(path.join(tmpdir(), "agent-comms-ledger-fs-"));
185
+ const tornWrite = pausingHeadWrites(createNodeFsStorage({ dir }));
186
+ const machineLock = `${dir}.lock`;
187
+ const replicator = new AccountLedger({
188
+ accountPrivateKey: account.privateKey,
189
+ writerNonce: generateWriterNonce(),
190
+ storage: tornWrite.storage,
191
+ lock: createFileLedgerLock(machineLock),
192
+ clock: createSystemClock(),
193
+ });
194
+ const readerQueued = Promise.withResolvers();
195
+ const readerLock = createFileLedgerLock(machineLock);
196
+ const reader = new AccountLedger({
197
+ accountPrivateKey: account.privateKey,
198
+ writerNonce: generateWriterNonce(),
199
+ storage: tornWrite.storage,
200
+ lock: {
201
+ run: async (critical) => {
202
+ readerQueued.resolve(undefined);
203
+ return readerLock.run(critical);
204
+ },
205
+ },
206
+ clock: createSystemClock(),
207
+ });
208
+ await origin.recordGrant("dm", "bearer", randomId());
209
+ await replicate(origin, replicator);
210
+ await origin.recordGrant("dm", "bearer", randomId());
211
+ const paused = tornWrite.pauseNextHeadWrite();
212
+ const replicating = replicate(origin, replicator);
213
+ await paused.reached;
214
+ const reading = reader.outstandingGrants("dm", "bearer");
215
+ // The read either finishes while the head is torn, or is queued behind the write; only then does the write complete.
216
+ await Promise.race([reading, readerQueued.promise]);
217
+ paused.release();
218
+ await replicating;
219
+ expect(await reading).toHaveLength(2);
220
+ fs.rmSync(dir, { recursive: true, force: true });
221
+ });
222
+ it("does not fork its writer log when several stores on one machine append at once", async () => {
223
+ const account = generateIdentity();
224
+ const shared = {
225
+ accountPrivateKey: account.privateKey,
226
+ writerNonce: generateWriterNonce(),
227
+ storage: createMemoryStorage(),
228
+ lock: createInProcessLedgerLock(),
229
+ clock: createSystemClock(),
230
+ };
231
+ const stores = [new AccountLedger(shared), new AccountLedger(shared)];
232
+ const issued = Array.from({ length: CONCURRENT_APPENDS }, () => randomId());
233
+ await Promise.all(issued.map(async (tokenId, index) => stores[index % stores.length]?.recordGrant("dm", "bearer", tokenId)));
234
+ const [first] = stores;
235
+ if (first === undefined)
236
+ throw new Error("expected a store");
237
+ expect(await tokenIds(first, "dm", "bearer")).toEqual(expect.arrayContaining(issued));
238
+ expect(await tokenIds(first, "dm", "bearer")).toHaveLength(issued.length);
239
+ });
240
+ });
241
+ describe("openAccountLedger", () => {
242
+ function userDir() {
243
+ return fs.mkdtempSync(path.join(tmpdir(), "agent-comms-account-ledger-"));
244
+ }
245
+ function writeLegacyGrants(dir) {
246
+ const file = path.join(dir, "user-identity.json");
247
+ const parsed = JSON.parse(fs.readFileSync(file, "utf-8"));
248
+ if (typeof parsed !== "object" || parsed === null) {
249
+ throw new Error("user-identity.json is not an object");
250
+ }
251
+ fs.writeFileSync(file, JSON.stringify({
252
+ ...parsed,
253
+ issuedDeviceGrants: {
254
+ "device-a": Buffer.from([1, 1]).toString("base64"),
255
+ },
256
+ issuedDmGrants: { "bearer-a": Buffer.from([2, 2]).toString("base64") },
257
+ }));
258
+ }
259
+ it("migrates an existing user-identity.json's issued grants into the ledger and removes them from the file", async () => {
260
+ const dir = userDir();
261
+ const userIdentity = loadOrCreateUserIdentity({ dir });
262
+ writeLegacyGrants(dir);
263
+ const ledger = await openAccountLedger({
264
+ userIdentityOptions: { dir },
265
+ userIdentity,
266
+ clock: createSystemClock(),
267
+ });
268
+ expect(await tokenIds(ledger, "device", "device-a")).toEqual([
269
+ Uint8Array.from([1, 1]),
270
+ ]);
271
+ expect(await tokenIds(ledger, "dm", "bearer-a")).toEqual([
272
+ Uint8Array.from([2, 2]),
273
+ ]);
274
+ expect(readLegacyIssuedGrants({ dir })).toEqual([]);
275
+ });
276
+ it("keeps migrated grants across a restart without recording them twice", async () => {
277
+ const dir = userDir();
278
+ const userIdentity = loadOrCreateUserIdentity({ dir });
279
+ writeLegacyGrants(dir);
280
+ const options = {
281
+ userIdentityOptions: { dir },
282
+ userIdentity,
283
+ clock: createSystemClock(),
284
+ };
285
+ await openAccountLedger(options);
286
+ const reopened = await openAccountLedger(options);
287
+ expect(await tokenIds(reopened, "device", "device-a")).toEqual([
288
+ Uint8Array.from([1, 1]),
289
+ ]);
290
+ const [have] = await reopened.announcements();
291
+ expect(have?.["head-seq"]).toBe(2);
292
+ });
293
+ it("replicates a migrated grant to another machine, which can then revoke it", async () => {
294
+ const dir = userDir();
295
+ const userIdentity = loadOrCreateUserIdentity({ dir });
296
+ writeLegacyGrants(dir);
297
+ const migrated = await openAccountLedger({
298
+ userIdentityOptions: { dir },
299
+ userIdentity,
300
+ clock: createSystemClock(),
301
+ });
302
+ const other = machineLedger(userIdentity);
303
+ await replicate(migrated, other);
304
+ const [grant] = await other.outstandingGrants("device", "device-a");
305
+ if (grant === undefined)
306
+ throw new Error("expected the migrated grant");
307
+ const revocation = await mintRevocationEntry({
308
+ identity: await toIdentityPort(userIdentity),
309
+ tokenId: grant.tokenId,
310
+ revokedAt: Date.now(),
311
+ });
312
+ await other.recordRevocation("device", "device-a", grant.tokenId, revocation);
313
+ await replicate(other, migrated);
314
+ expect(await tokenIds(migrated, "device", "device-a")).toEqual([]);
315
+ });
316
+ });
317
+ //# sourceMappingURL=account-ledger.unit.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-ledger.unit.test.js","sourceRoot":"","sources":["../../src/test/account-ledger.unit.test.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wCAAwC,CAAC;AAC7E,OAAO,EAAE,mBAAmB,EAAE,MAAM,yCAAyC,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAQnE,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,aAAa,EACb,eAAe,EACf,eAAe,EACf,WAAW,GACZ,MAAM,kCAAkC,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iCAAiC,CAAC;AACpE,OAAO,EAAE,gBAAgB,EAAqB,MAAM,qBAAqB,CAAC;AAC1E,OAAO,EACL,oBAAoB,EACpB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAChD,OAAO,EACL,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAI/D,+HAA+H;AAC/H,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAE7B,sJAAsJ;AACtJ,SAAS,aAAa,CAAC,OAA+B;IACpD,OAAO,IAAI,aAAa,CAAC;QACvB,iBAAiB,EAAE,OAAO,CAAC,UAAU;QACrC,WAAW,EAAE,mBAAmB,EAAE;QAClC,OAAO,EAAE,mBAAmB,EAAE;QAC9B,IAAI,EAAE,yBAAyB,EAAE;QACjC,KAAK,EAAE,iBAAiB,EAAE;KAC3B,CAAC,CAAC;AACL,CAAC;AAED,oPAAoP;AACpP,SAAS,iBAAiB,CAAC,KAAgC;IAOzD,IAAI,OAAyE,CAAC;IAC9E,MAAM,OAAO,GAAoB;QAC/B,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;QAClC,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;QACxC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;QAC1C,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE;YACxB,MAAM,KAAK,GAAG,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC;YAC1D,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;gBACxB,OAAO,GAAG,SAAS,CAAC;gBACpB,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,UAAU,EAAE,CAAC,CAAC;gBACvC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACf,MAAM,KAAK,CAAC,QAAQ,CAAC;YACvB,CAAC;YACD,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9B,CAAC;KACF,CAAC;IACF,OAAO;QACL,OAAO;QACP,kBAAkB,EAAE,GAAG,EAAE;YACvB,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,EAAa,CAAC;YACnD,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,EAAa,CAAC;YACpD,OAAO,GAAG;gBACR,MAAM,EAAE,GAAG,EAAE;oBACX,OAAO,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAC7B,CAAC;gBACD,QAAQ,EAAE,QAAQ,CAAC,OAAO;aAC3B,CAAC;YACF,OAAO;gBACL,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,OAAO,EAAE,GAAG,EAAE;oBACZ,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;gBAC9B,CAAC;aACF,CAAC;QACJ,CAAC;KACF,CAAC;AACJ,CAAC;AAED,gLAAgL;AAChL,KAAK,UAAU,SAAS,CACtB,IAAmB,EACnB,EAAiB;IAEjB,KAAK,MAAM,IAAI,IAAI,MAAM,IAAI,CAAC,aAAa,EAAE,EAAE,CAAC;QAC9C,IAAI,IAAI,GAAuB,MAAM,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QAC9D,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;YACrD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;YACjD,IAAI,OAAO,KAAK,IAAI;gBAAE,MAAM;YAC5B,MAAM,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,GAAG,MAAM,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;AACH,CAAC;AAED,KAAK,UAAU,QAAQ,CACrB,MAAqB,EACrB,IAAqB,EACrB,OAAe;IAEf,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC7D,OAAO,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;AAC9C,CAAC;AAED,QAAQ,CAAC,wBAAwB,EAAE,GAAG,EAAE;IACtC,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,uBAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACzD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,QAAQ,EAAE,CAAC;IAE7B,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;QAC7D,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACxD,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yFAAyF,EAAE,GAAG,EAAE;QACjG,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QACxD,MAAM,QAAQ,GAAG,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;QAC1D,MAAM,SAAS,GAAG,uBAAuB,CAAC,gBAAgB,EAAE,CAAC,UAAU,CAAC,CAAC;QAEzE,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QAC9D,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;QACnE,MAAM,CAAC,eAAe,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC;IACrE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,SAAS,GAAG,uBAAuB,CAAC,gBAAgB,EAAE,CAAC,UAAU,CAAC,CAAC;QAEzE,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC5C,MAAM,CAAC,aAAa,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClD,MAAM,CAAC,aAAa,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,GAAG,EAAE;QAClE,MAAM,IAAI,GAAG,uBAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;QAExD,MAAM,CAAC,eAAe,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACnE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,EAAE,CAAC,+EAA+E,EAAE,KAAK,IAAI,EAAE;QAC7F,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,WAAW,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC;QAE3B,MAAM,KAAK,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;QAExE,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC;YAC3C,QAAQ,EAAE,WAAW;YACrB,OAAO;YACP,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,gBAAgB,CAAC,QAAQ,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QACzE,MAAM,OAAO,GAAsB,EAAE,CAAC;QACtC,KAAK,CAAC,sBAAsB,CAAC,CAAC,KAAK,EAAE,EAAE;YACrC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QACH,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAE/B,MAAM,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QACtC,MAAM,CAAC,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2DAA2D,EAAE,KAAK,IAAI,EAAE;QACzE,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,SAAS,GAAG,QAAQ,EAAE,CAAC;QAC7B,MAAM,UAAU,GAAG,QAAQ,EAAE,CAAC;QAE9B,MAAM,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;QACnD,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAC/B,MAAM,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QAE/B,KAAK,MAAM,MAAM,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;YACrC,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CACpD,MAAM,CAAC,eAAe,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC,CAChD,CAAC;YACF,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACjE,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uFAAuF,EAAE,KAAK,IAAI,EAAE;QACrG,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,IAAI,GAAG,uBAAuB,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,WAAW,CAAC,IAAI,EAAE,mBAAmB,EAAE,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,eAAe,CAC5B,uBAAuB,CAAC,gBAAgB,EAAE,CAAC,UAAU,CAAC,EACtD,GAAG,EACH,CAAC,EACD,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CACrB,CAAC;QAEF,MAAM,MAAM,CAAC,eAAe,CAAC;YAC3B,IAAI,EAAE,cAAc;YACpB,IAAI,EAAE,GAAG;YACT,UAAU,EAAE,CAAC;YACb,OAAO,EAAE,CAAC,MAAM,CAAC;SAClB,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACvC,MAAM,CAAC,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,QAAQ,GAAG,aAAa,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAEnD,MAAM,MAAM,CAAC,WAAW,CAAC,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;QAC3D,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;QAC5C,IAAI,IAAI,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAEpE,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;QACvG,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,GAAG,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,wBAAwB,CAAC,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,iBAAiB,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC;QAClE,MAAM,WAAW,GAAG,GAAG,GAAG,OAAO,CAAC;QAClC,MAAM,UAAU,GAAG,IAAI,aAAa,CAAC;YACnC,iBAAiB,EAAE,OAAO,CAAC,UAAU;YACrC,WAAW,EAAE,mBAAmB,EAAE;YAClC,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,IAAI,EAAE,oBAAoB,CAAC,WAAW,CAAC;YACvC,KAAK,EAAE,iBAAiB,EAAE;SAC3B,CAAC,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,CAAC,aAAa,EAAa,CAAC;QACxD,MAAM,UAAU,GAAG,oBAAoB,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,MAAM,GAAG,IAAI,aAAa,CAAC;YAC/B,iBAAiB,EAAE,OAAO,CAAC,UAAU;YACrC,WAAW,EAAE,mBAAmB,EAAE;YAClC,OAAO,EAAE,SAAS,CAAC,OAAO;YAC1B,IAAI,EAAE;gBACJ,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE;oBACtB,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;oBAChC,OAAO,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;gBAClC,CAAC;aACF;YACD,KAAK,EAAE,iBAAiB,EAAE;SAC3B,CAAC,CAAC;QACH,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QACpC,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC;QAErD,MAAM,MAAM,GAAG,SAAS,CAAC,kBAAkB,EAAE,CAAC;QAC9C,MAAM,WAAW,GAAG,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAClD,MAAM,MAAM,CAAC,OAAO,CAAC;QACrB,MAAM,OAAO,GAAG,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACzD,qHAAqH;QACrH,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;QACpD,MAAM,CAAC,OAAO,EAAE,CAAC;QACjB,MAAM,WAAW,CAAC;QAElB,MAAM,CAAC,MAAM,OAAO,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;QACtC,EAAE,CAAC,MAAM,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAC9F,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG;YACb,iBAAiB,EAAE,OAAO,CAAC,UAAU;YACrC,WAAW,EAAE,mBAAmB,EAAE;YAClC,OAAO,EAAE,mBAAmB,EAAE;YAC9B,IAAI,EAAE,yBAAyB,EAAE;YACjC,KAAK,EAAE,iBAAiB,EAAE;SAC3B,CAAC;QACF,MAAM,MAAM,GAAG,CAAC,IAAI,aAAa,CAAC,MAAM,CAAC,EAAE,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC;QACtE,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,kBAAkB,EAAE,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC;QAE5E,MAAM,OAAO,CAAC,GAAG,CACf,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,CAClC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CACpE,CACF,CAAC;QAEF,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC;QACvB,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC;QAC7D,MAAM,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,OAAO,CACnD,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAC/B,CAAC;QACF,MAAM,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5E,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,mBAAmB,EAAE,GAAG,EAAE;IACjC,SAAS,OAAO;QACd,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,6BAA6B,CAAC,CAAC,CAAC;IAC5E,CAAC;IAED,SAAS,iBAAiB,CAAC,GAAW;QACpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;QAClD,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QACnE,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAClD,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QACD,EAAE,CAAC,aAAa,CACd,IAAI,EACJ,IAAI,CAAC,SAAS,CAAC;YACb,GAAG,MAAM;YACT,kBAAkB,EAAE;gBAClB,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;aACnD;YACD,cAAc,EAAE,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE;SACvE,CAAC,CACH,CAAC;IACJ,CAAC;IAED,EAAE,CAAC,wGAAwG,EAAE,KAAK,IAAI,EAAE;QACtH,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,wBAAwB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,iBAAiB,CAAC,GAAG,CAAC,CAAC;QAEvB,MAAM,MAAM,GAAG,MAAM,iBAAiB,CAAC;YACrC,mBAAmB,EAAE,EAAE,GAAG,EAAE;YAC5B,YAAY;YACZ,KAAK,EAAE,iBAAiB,EAAE;SAC3B,CAAC,CAAC;QAEH,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;YAC3D,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACxB,CAAC,CAAC;QACH,MAAM,CAAC,MAAM,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;YACvD,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACxB,CAAC,CAAC;QACH,MAAM,CAAC,sBAAsB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,wBAAwB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,OAAO,GAAG;YACd,mBAAmB,EAAE,EAAE,GAAG,EAAE;YAC5B,YAAY;YACZ,KAAK,EAAE,iBAAiB,EAAE;SAC3B,CAAC;QAEF,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QACjC,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAElD,MAAM,CAAC,MAAM,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC;YAC7D,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;SACxB,CAAC,CAAC;QACH,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;QACxF,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;QACtB,MAAM,YAAY,GAAG,wBAAwB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;QACvD,iBAAiB,CAAC,GAAG,CAAC,CAAC;QACvB,MAAM,QAAQ,GAAG,MAAM,iBAAiB,CAAC;YACvC,mBAAmB,EAAE,EAAE,GAAG,EAAE;YAC5B,YAAY;YACZ,KAAK,EAAE,iBAAiB,EAAE;SAC3B,CAAC,CAAC;QACH,MAAM,KAAK,GAAG,aAAa,CAAC,YAAY,CAAC,CAAC;QAE1C,MAAM,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,iBAAiB,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;QACpE,IAAI,KAAK,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;QACxE,MAAM,UAAU,GAAG,MAAM,mBAAmB,CAAC;YAC3C,QAAQ,EAAE,MAAM,cAAc,CAAC,YAAY,CAAC;YAC5C,OAAO,EAAE,KAAK,CAAC,OAAO;YACtB,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAC,CAAC;QACH,MAAM,KAAK,CAAC,gBAAgB,CAC1B,QAAQ,EACR,UAAU,EACV,KAAK,CAAC,OAAO,EACb,UAAU,CACX,CAAC;QACF,MAAM,SAAS,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAEjC,MAAM,CAAC,MAAM,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACrE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Unit tests for the account key's export and import (agent-comms#344): the passphrase-sealed bundle, the `account export`/`account import` commands built on it, and what importing does to the machine it lands on.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=account-transfer.unit.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"account-transfer.unit.test.d.ts","sourceRoot":"","sources":["../../src/test/account-transfer.unit.test.ts"],"names":[],"mappings":"AAAA;;GAEG"}