agent-comms 3.15.0 → 3.16.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 (84) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/README.md +52 -1
  4. package/dist/core/bridge-mesh.d.ts +1 -1
  5. package/dist/core/bridge-mesh.js +1 -1
  6. package/dist/core/bridge.d.ts +10 -0
  7. package/dist/core/bridge.d.ts.map +1 -1
  8. package/dist/core/bridge.js +40 -1
  9. package/dist/core/bridge.js.map +1 -1
  10. package/dist/core/connection-code-tool.d.ts +18 -0
  11. package/dist/core/connection-code-tool.d.ts.map +1 -0
  12. package/dist/core/connection-code-tool.js +74 -0
  13. package/dist/core/connection-code-tool.js.map +1 -0
  14. package/dist/core/connection-code.d.ts +65 -0
  15. package/dist/core/connection-code.d.ts.map +1 -0
  16. package/dist/core/connection-code.js +180 -0
  17. package/dist/core/connection-code.js.map +1 -0
  18. package/dist/core/dm-send-delegation.d.ts +32 -0
  19. package/dist/core/dm-send-delegation.d.ts.map +1 -0
  20. package/dist/core/dm-send-delegation.js +35 -0
  21. package/dist/core/dm-send-delegation.js.map +1 -0
  22. package/dist/core/gateway-trust.d.ts +20 -5
  23. package/dist/core/gateway-trust.d.ts.map +1 -1
  24. package/dist/core/gateway-trust.js +37 -7
  25. package/dist/core/gateway-trust.js.map +1 -1
  26. package/dist/core/identity-store.d.ts +28 -4
  27. package/dist/core/identity-store.d.ts.map +1 -1
  28. package/dist/core/identity-store.js +82 -8
  29. package/dist/core/identity-store.js.map +1 -1
  30. package/dist/core/mesh-store.d.ts +13 -4
  31. package/dist/core/mesh-store.d.ts.map +1 -1
  32. package/dist/core/mesh-store.js +24 -5
  33. package/dist/core/mesh-store.js.map +1 -1
  34. package/dist/core/pgp-keyserver.d.ts +12 -0
  35. package/dist/core/pgp-keyserver.d.ts.map +1 -0
  36. package/dist/core/pgp-keyserver.js +22 -0
  37. package/dist/core/pgp-keyserver.js.map +1 -0
  38. package/dist/core/room-lifecycle.d.ts +3 -1
  39. package/dist/core/room-lifecycle.d.ts.map +1 -1
  40. package/dist/core/room-lifecycle.js +4 -3
  41. package/dist/core/room-lifecycle.js.map +1 -1
  42. package/dist/core/tool.d.ts +11 -2
  43. package/dist/core/tool.d.ts.map +1 -1
  44. package/dist/core/tool.js +12 -2
  45. package/dist/core/tool.js.map +1 -1
  46. package/dist/core/types.d.ts +41 -0
  47. package/dist/core/types.d.ts.map +1 -1
  48. package/dist/core/types.js +25 -0
  49. package/dist/core/types.js.map +1 -1
  50. package/dist/test/connection-code-ledger-persistence.test.d.ts +5 -0
  51. package/dist/test/connection-code-ledger-persistence.test.d.ts.map +1 -0
  52. package/dist/test/connection-code-ledger-persistence.test.js +84 -0
  53. package/dist/test/connection-code-ledger-persistence.test.js.map +1 -0
  54. package/dist/test/connection-code-tool.test.d.ts +2 -0
  55. package/dist/test/connection-code-tool.test.d.ts.map +1 -0
  56. package/dist/test/connection-code-tool.test.js +296 -0
  57. package/dist/test/connection-code-tool.test.js.map +1 -0
  58. package/dist/test/connection-code.test.d.ts +5 -0
  59. package/dist/test/connection-code.test.d.ts.map +1 -0
  60. package/dist/test/connection-code.test.js +236 -0
  61. package/dist/test/connection-code.test.js.map +1 -0
  62. package/dist/test/dm-send-capability-admission.integration.test.js +82 -1
  63. package/dist/test/dm-send-capability-admission.integration.test.js.map +1 -1
  64. package/dist/test/dm-send-delegation.test.d.ts +2 -0
  65. package/dist/test/dm-send-delegation.test.d.ts.map +1 -0
  66. package/dist/test/dm-send-delegation.test.js +146 -0
  67. package/dist/test/dm-send-delegation.test.js.map +1 -0
  68. package/dist/test/dm-send-principal-delegation.integration.test.d.ts +2 -0
  69. package/dist/test/dm-send-principal-delegation.integration.test.d.ts.map +1 -0
  70. package/dist/test/dm-send-principal-delegation.integration.test.js +89 -0
  71. package/dist/test/dm-send-principal-delegation.integration.test.js.map +1 -0
  72. package/dist/test/gateway-trust.test.js +92 -0
  73. package/dist/test/gateway-trust.test.js.map +1 -1
  74. package/dist/test/identity-store.test.js +42 -18
  75. package/dist/test/identity-store.test.js.map +1 -1
  76. package/dist/test/pgp-keyserver.test.d.ts +5 -0
  77. package/dist/test/pgp-keyserver.test.d.ts.map +1 -0
  78. package/dist/test/pgp-keyserver.test.js +24 -0
  79. package/dist/test/pgp-keyserver.test.js.map +1 -0
  80. package/dist/test/test-transport.d.ts +2 -1
  81. package/dist/test/test-transport.d.ts.map +1 -1
  82. package/dist/test/test-transport.js +5 -5
  83. package/dist/test/test-transport.js.map +1 -1
  84. package/package.json +2 -1
@@ -1,12 +1,24 @@
1
1
  /**
2
2
  * Integration test for receiver-side DM gating with a user-issued capability (agent-comms#162): a receiver's own user principal can admit an agent into its DM-communication scope by minting a dm:send grant, which the agent then presents alongside its DM join request to auto-admit without needing a fresh human decision each time -- the durable admission list this issue adds, distinct from (and additive to) dm-admission.integration.test.ts's own two-round human-consent flow, which remains the fallback when no dm:send grant is presented at all.
3
3
  */
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { tmpdir } from "node:os";
4
7
  import { test, expect } from "vitest";
5
- import { deviceIdFromHex } from "wire-mesh-core/domain/device-id";
8
+ import { deviceIdFromHex, deviceIdToHex, } from "wire-mesh-core/domain/device-id";
9
+ import { mintCapabilityToken } from "wire-mesh-core/domain/tokens";
10
+ import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
6
11
  import { MeshStore } from "../core/mesh-store.js";
12
+ import { generateIdentity } from "../core/identity.js";
13
+ import { toIdentityPort } from "../core/wire-mesh-identity.js";
14
+ import { randomId } from "../core/random-id.js";
15
+ import { loadOrCreateUserIdentity } from "../core/user-identity.js";
16
+ import { DM_SEND_CAPABILITY } from "../core/dm-token-verification.js";
7
17
  import { waitFor, wireTestTransport } from "./test-transport.js";
8
18
  /** A device-id, hex-encoded, is always exactly this many characters (32 raw bytes). */
9
19
  const DEVICE_ID_HEX_LENGTH = 64;
20
+ /** Expiry window for a delegated dm:send token minted directly in these tests (agent-comms#187) -- comfortably longer than any single test run, matching device-membership.test.ts's own TOKEN_TTL_MS convention. */
21
+ const DELEGATED_TOKEN_TTL_MS = 60_000;
10
22
  let nextPort = 20_990;
11
23
  function freshPort() {
12
24
  nextPort += 1;
@@ -87,4 +99,73 @@ test("revoking a bearer that was never admitted is a harmless no-op", async () =
87
99
  await a.shutdown();
88
100
  }
89
101
  });
102
+ /** B's own user-principal identity, loaded from a directory this test controls directly (rather than the throwaway one wireTestTransport would otherwise generate internally and never disclose), so a test can compute the exact "user" scope path (B's own principal device-id, hex) a dm:send grant B mints is rooted at -- agent-comms#187's own principal-keyed admission tests need this to construct a further delegation whose scope actually narrows the grant it chains from. */
103
+ function tempUserIdentityDir() {
104
+ return {
105
+ dir: fs.mkdtempSync(path.join(tmpdir(), "agent-comms-b-user-identity-test-")),
106
+ };
107
+ }
108
+ test("admitting a bearer with a positive delegationsRemaining lets that bearer itself mint a further dm:send delegation (agent-comms#187)", async () => {
109
+ const bUserIdentityOptions = tempUserIdentityDir();
110
+ const bPrincipalHex = deviceIdToHex((await toIdentityPort(loadOrCreateUserIdentity(bUserIdentityOptions)))
111
+ .deviceId);
112
+ const clock = createSystemClock();
113
+ const b = new MeshStore(freshPort());
114
+ await wireTestTransport(b, undefined, undefined, undefined, bUserIdentityOptions);
115
+ await b.init();
116
+ try {
117
+ // The admitted bearer is a real principal identity here, not just a bare hex string -- only the entity actually holding bearerId's own key can mint a delegation of the grant, since mintCapabilityToken's own parent-narrowing requires the child's issuer to equal the parent's bearer.
118
+ const principal = await toIdentityPort(generateIdentity());
119
+ const bearerHex = deviceIdToHex(principal.deviceId);
120
+ const grant = await b.admitAgentForDm(bearerHex, 1);
121
+ const device = await toIdentityPort(generateIdentity());
122
+ const delegated = await mintCapabilityToken({
123
+ identity: principal,
124
+ clock,
125
+ tokenId: randomId(),
126
+ bearer: device.deviceId,
127
+ capability: DM_SEND_CAPABILITY,
128
+ scope: { kind: "user", path: bPrincipalHex },
129
+ expires: clock.now() + DELEGATED_TOKEN_TTL_MS,
130
+ delegationsRemaining: 0,
131
+ parent: grant,
132
+ });
133
+ expect(delegated.ok, `expected the delegation to succeed, got ${JSON.stringify(delegated)}`).toBe(true);
134
+ }
135
+ finally {
136
+ await b.shutdown();
137
+ }
138
+ });
139
+ test("admitting a bearer with no delegationsRemaining given stays non-delegable, exactly like the existing bare-device path", async () => {
140
+ const bUserIdentityOptions = tempUserIdentityDir();
141
+ const bPrincipalHex = deviceIdToHex((await toIdentityPort(loadOrCreateUserIdentity(bUserIdentityOptions)))
142
+ .deviceId);
143
+ const clock = createSystemClock();
144
+ const b = new MeshStore(freshPort());
145
+ await wireTestTransport(b, undefined, undefined, undefined, bUserIdentityOptions);
146
+ await b.init();
147
+ try {
148
+ const principal = await toIdentityPort(generateIdentity());
149
+ const bearerHex = deviceIdToHex(principal.deviceId);
150
+ const grant = await b.admitAgentForDm(bearerHex);
151
+ const device = await toIdentityPort(generateIdentity());
152
+ const delegated = await mintCapabilityToken({
153
+ identity: principal,
154
+ clock,
155
+ tokenId: randomId(),
156
+ bearer: device.deviceId,
157
+ capability: DM_SEND_CAPABILITY,
158
+ scope: { kind: "user", path: bPrincipalHex },
159
+ expires: clock.now() + DELEGATED_TOKEN_TTL_MS,
160
+ delegationsRemaining: 0,
161
+ parent: grant,
162
+ });
163
+ expect(delegated.ok).toBe(false);
164
+ if (!delegated.ok)
165
+ expect(delegated.reason).toBe("delegation_exceeds_parent");
166
+ }
167
+ finally {
168
+ await b.shutdown();
169
+ }
170
+ });
90
171
  //# sourceMappingURL=dm-send-capability-admission.integration.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"dm-send-capability-admission.integration.test.js","sourceRoot":"","sources":["../../src/test/dm-send-capability-admission.integration.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"dm-send-capability-admission.integration.test.js","sourceRoot":"","sources":["../../src/test/dm-send-capability-admission.integration.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dm-send-delegation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dm-send-delegation.test.d.ts","sourceRoot":"","sources":["../../src/test/dm-send-delegation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,146 @@
1
+ /**
2
+ * Unit tests for core/dm-send-delegation: delegateDmSendToDevice, the primitive that lets a user principal already admitted into a remote user's DM-communication scope (room-lifecycle.ts's admitAgentForDm, minted with delegationsRemaining \> 0) sub-delegate that admission to one of its own devices (agent-comms#187) -- the dm:send counterpart to device-membership.test.ts's own admitDevice/removeDevice coverage.
3
+ */
4
+ import * as fs from "node:fs";
5
+ import { tmpdir } from "node:os";
6
+ import path from "node:path";
7
+ import { describe, it, expect } from "vitest";
8
+ import { deviceIdToHex } from "wire-mesh-core/domain/device-id";
9
+ import { mintCapabilityToken } from "wire-mesh-core/domain/tokens";
10
+ import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
11
+ import { createRevocationView } from "wire-mesh-core/domain/revocation-view";
12
+ import { generateIdentity } from "../core/identity.js";
13
+ import { toIdentityPort } from "../core/wire-mesh-identity.js";
14
+ import { randomId } from "../core/random-id.js";
15
+ import { loadIssuedDmGrant, loadOrCreateUserIdentity, } from "../core/user-identity.js";
16
+ import { DM_SEND_CAPABILITY, DM_SEND_SCOPE_KIND, verifyDmSendToken, } from "../core/dm-token-verification.js";
17
+ import { delegateDmSendToDevice } from "../core/dm-send-delegation.js";
18
+ const TOKEN_TTL_MS = 60_000;
19
+ const NON_DELEGABLE = 0;
20
+ const ONE_HOP_DELEGABLE = 1;
21
+ function tempDir() {
22
+ return fs.mkdtempSync(path.join(tmpdir(), "agent-comms-dm-delegation-test-"));
23
+ }
24
+ /** A real, persisted user-principal identity -- delegateDmSendToDevice writes through to the same user-identity.json this identity's own key material lives in, so the fixture must actually create that file first, the same way device-membership.test.ts's own makeUser() does. */
25
+ async function makeUser() {
26
+ const dir = tempDir();
27
+ const identity = await toIdentityPort(loadOrCreateUserIdentity({ dir }));
28
+ return { identity, userIdentityOptions: { dir } };
29
+ }
30
+ /** Alice's own root-level dm:send grant naming bearer as the admitted party -- the same shape room-lifecycle.ts's admitAgentForDm mints, built directly here so this file's own tests don't need a full MeshStore. Takes an explicit expires (rather than deriving one from clock.now() itself) so a caller can mint a child token sharing the identical expiry -- a real wall clock advances between two calls, and a child's own expires must never exceed its parent's. */
31
+ async function mintRootGrant(admitter, bearer, clock, delegationsRemaining, expires) {
32
+ const verdict = await mintCapabilityToken({
33
+ identity: admitter,
34
+ clock,
35
+ tokenId: randomId(),
36
+ bearer,
37
+ capability: DM_SEND_CAPABILITY,
38
+ scope: { kind: DM_SEND_SCOPE_KIND, path: deviceIdToHex(admitter.deviceId) },
39
+ expires,
40
+ delegationsRemaining,
41
+ });
42
+ if (!verdict.ok)
43
+ throw new Error("expected root grant to mint");
44
+ return verdict.token;
45
+ }
46
+ describe("delegateDmSendToDevice", () => {
47
+ it("mints a dm:send token bearing the device, chaining back to the remote admitting principal", async () => {
48
+ const alice = await toIdentityPort(generateIdentity());
49
+ const { identity: bobPrincipal, userIdentityOptions } = await makeUser();
50
+ const bobDevice = await toIdentityPort(generateIdentity());
51
+ const clock = createSystemClock();
52
+ const expires = clock.now() + TOKEN_TTL_MS;
53
+ const grant = await mintRootGrant(alice, bobPrincipal.deviceId, clock, ONE_HOP_DELEGABLE, expires);
54
+ const verdict = await delegateDmSendToDevice({
55
+ userIdentity: bobPrincipal,
56
+ userIdentityOptions,
57
+ clock,
58
+ tokenId: randomId(),
59
+ parent: grant,
60
+ deviceId: bobDevice.deviceId,
61
+ remoteUserPrincipalDeviceId: alice.deviceId,
62
+ expires,
63
+ });
64
+ expect(verdict.ok, `expected delegation to succeed, got ${JSON.stringify(verdict)}`).toBe(true);
65
+ if (!verdict.ok)
66
+ return;
67
+ const checked = await verifyDmSendToken(verdict.token, {
68
+ identity: alice,
69
+ clock,
70
+ revocation: createRevocationView(),
71
+ expectedBearer: bobDevice.deviceId,
72
+ userPrincipalDeviceId: alice.deviceId,
73
+ });
74
+ expect(checked.ok, JSON.stringify(checked)).toBe(true);
75
+ });
76
+ it("records the delegated grant's token-id under the delegating principal's own store, keyed by device hex", async () => {
77
+ const alice = await toIdentityPort(generateIdentity());
78
+ const { identity: bobPrincipal, userIdentityOptions } = await makeUser();
79
+ const bobDevice = await toIdentityPort(generateIdentity());
80
+ const clock = createSystemClock();
81
+ const tokenId = randomId();
82
+ const expires = clock.now() + TOKEN_TTL_MS;
83
+ const grant = await mintRootGrant(alice, bobPrincipal.deviceId, clock, ONE_HOP_DELEGABLE, expires);
84
+ const verdict = await delegateDmSendToDevice({
85
+ userIdentity: bobPrincipal,
86
+ userIdentityOptions,
87
+ clock,
88
+ tokenId,
89
+ parent: grant,
90
+ deviceId: bobDevice.deviceId,
91
+ remoteUserPrincipalDeviceId: alice.deviceId,
92
+ expires,
93
+ });
94
+ expect(verdict.ok).toBe(true);
95
+ const deviceHex = deviceIdToHex(bobDevice.deviceId);
96
+ expect(loadIssuedDmGrant(userIdentityOptions, deviceHex)).toEqual(tokenId);
97
+ });
98
+ it("refuses when the parent grant carries no further delegation depth, and records nothing", async () => {
99
+ const alice = await toIdentityPort(generateIdentity());
100
+ const { identity: bobPrincipal, userIdentityOptions } = await makeUser();
101
+ const bobDevice = await toIdentityPort(generateIdentity());
102
+ const clock = createSystemClock();
103
+ const expires = clock.now() + TOKEN_TTL_MS;
104
+ // The original, non-delegable admission -- exactly what admitAgentForDm mints by default.
105
+ const grant = await mintRootGrant(alice, bobPrincipal.deviceId, clock, NON_DELEGABLE, expires);
106
+ const verdict = await delegateDmSendToDevice({
107
+ userIdentity: bobPrincipal,
108
+ userIdentityOptions,
109
+ clock,
110
+ tokenId: randomId(),
111
+ parent: grant,
112
+ deviceId: bobDevice.deviceId,
113
+ remoteUserPrincipalDeviceId: alice.deviceId,
114
+ expires,
115
+ });
116
+ expect(verdict.ok).toBe(false);
117
+ if (!verdict.ok)
118
+ expect(verdict.reason).toBe("delegation_exceeds_parent");
119
+ const deviceHex = deviceIdToHex(bobDevice.deviceId);
120
+ expect(loadIssuedDmGrant(userIdentityOptions, deviceHex)).toBeUndefined();
121
+ });
122
+ it("refuses when the caller's identity is not the parent grant's own bearer", async () => {
123
+ const alice = await toIdentityPort(generateIdentity());
124
+ const { identity: bobPrincipal, userIdentityOptions } = await makeUser();
125
+ const someoneElse = await toIdentityPort(generateIdentity());
126
+ const bobDevice = await toIdentityPort(generateIdentity());
127
+ const clock = createSystemClock();
128
+ const expires = clock.now() + TOKEN_TTL_MS;
129
+ const grant = await mintRootGrant(alice, bobPrincipal.deviceId, clock, ONE_HOP_DELEGABLE, expires);
130
+ const verdict = await delegateDmSendToDevice({
131
+ // someoneElse never received this grant -- only bobPrincipal (the parent's own bearer) may mint a delegation of it.
132
+ userIdentity: someoneElse,
133
+ userIdentityOptions,
134
+ clock,
135
+ tokenId: randomId(),
136
+ parent: grant,
137
+ deviceId: bobDevice.deviceId,
138
+ remoteUserPrincipalDeviceId: alice.deviceId,
139
+ expires,
140
+ });
141
+ expect(verdict.ok).toBe(false);
142
+ if (!verdict.ok)
143
+ expect(verdict.reason).toBe("parent_bearer_mismatch");
144
+ });
145
+ });
146
+ //# sourceMappingURL=dm-send-delegation.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dm-send-delegation.test.js","sourceRoot":"","sources":["../../src/test/dm-send-delegation.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=dm-send-principal-delegation.integration.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dm-send-principal-delegation.integration.test.d.ts","sourceRoot":"","sources":["../../src/test/dm-send-principal-delegation.integration.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * End-to-end integration test for agent-comms#187: a user principal admitted into another user's DM-communication scope with room delegation depth (admitAgentForDm) mints, via delegateDmSendToDevice, a further dm:send token naming one of its own devices as bearer -- and that device's own requestDmAccess, presenting only the delegated token, auto-admits exactly the way a directly-admitted bare device already does in dm-send-capability-admission.integration.test.ts. Proves the full "trust this whole person, not just one of their devices" flow the issue names, end to end over a real wire connection.
3
+ */
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { tmpdir } from "node:os";
7
+ import { test, expect } from "vitest";
8
+ import { deviceIdFromHex, deviceIdToHex, } from "wire-mesh-core/domain/device-id";
9
+ import { createSystemClock } from "wire-mesh-core/adapters/system-clock";
10
+ import { MeshStore } from "../core/mesh-store.js";
11
+ import { loadOrCreateUserIdentity } from "../core/user-identity.js";
12
+ import { toIdentityPort } from "../core/wire-mesh-identity.js";
13
+ import { randomId } from "../core/random-id.js";
14
+ import { delegateDmSendToDevice } from "../core/dm-send-delegation.js";
15
+ import { waitFor, wireTestTransport } from "./test-transport.js";
16
+ /** Delegated token expiry -- comfortably longer than a single test run, matching this file's sibling integration tests' own convention. */
17
+ const DELEGATED_TOKEN_TTL_MS = 60_000;
18
+ /** The admitted principal keeps exactly one further hop of delegation depth, enough to reach one of its own devices -- the minimal case the issue itself describes ("sub-delegate to its own devices"). */
19
+ const ONE_HOP_DELEGABLE = 1;
20
+ let nextPort = 20_970;
21
+ function freshPort() {
22
+ nextPort += 1;
23
+ return nextPort;
24
+ }
25
+ function tempUserIdentityDir() {
26
+ return {
27
+ dir: fs.mkdtempSync(path.join(tmpdir(), "agent-comms-principal-delegation-test-")),
28
+ };
29
+ }
30
+ test("a principal's own device, holding only a delegated dm:send token, auto-admits into the admitting user's DM scope", async () => {
31
+ const port = freshPort();
32
+ // Alice's own user-principal identity is controlled directly (not the throwaway one wireTestTransport would otherwise generate and never disclose), so this test can compute the exact "user" scope path a delegated token must keep naming.
33
+ const aliceUserIdentityOptions = tempUserIdentityDir();
34
+ const alicePrincipal = await toIdentityPort(loadOrCreateUserIdentity(aliceUserIdentityOptions));
35
+ const a = new MeshStore(port);
36
+ await wireTestTransport(a, undefined, undefined, undefined, aliceUserIdentityOptions);
37
+ await a.init();
38
+ await a.registerAgent({
39
+ name: "alice",
40
+ harness: "test",
41
+ cwd: "/test/alice",
42
+ pid: process.pid,
43
+ visibility: "visible",
44
+ tags: [],
45
+ });
46
+ // Bob's own user-principal identity -- distinct from any bridge-slot device identity, and distinct from any of Bob's own devices below.
47
+ const bobUserIdentityOptions = tempUserIdentityDir();
48
+ const bobPrincipal = await toIdentityPort(loadOrCreateUserIdentity(bobUserIdentityOptions));
49
+ // One of Bob's own devices -- an ordinary bridge slot, wired and connected to Alice exactly like any other peer.
50
+ const d = new MeshStore(port);
51
+ await wireTestTransport(d);
52
+ await d.init();
53
+ await d.registerAgent({
54
+ name: "bobs-device",
55
+ harness: "test",
56
+ cwd: "/test/bobs-device",
57
+ pid: process.pid,
58
+ visibility: "visible",
59
+ tags: [],
60
+ });
61
+ await waitFor(() => a.serialise().agents[d.peerId] !== undefined, "alice sees bob's device");
62
+ try {
63
+ // Alice trusts Bob's own principal -- not this specific device -- with enough delegation depth for Bob to admit his own devices.
64
+ const grant = await a.admitAgentForDm(deviceIdToHex(bobPrincipal.deviceId), ONE_HOP_DELEGABLE);
65
+ // Bob's principal delegates that admission to this one device, out of band from Alice entirely -- Alice never learns this device's own device-id in advance.
66
+ const clock = createSystemClock();
67
+ const delegated = await delegateDmSendToDevice({
68
+ userIdentity: bobPrincipal,
69
+ userIdentityOptions: bobUserIdentityOptions,
70
+ clock,
71
+ tokenId: randomId(),
72
+ parent: grant,
73
+ deviceId: deviceIdFromHex(d.peerId),
74
+ remoteUserPrincipalDeviceId: alicePrincipal.deviceId,
75
+ expires: clock.now() + DELEGATED_TOKEN_TTL_MS,
76
+ });
77
+ expect(delegated.ok, `expected the delegation to succeed, got ${JSON.stringify(delegated)}`).toBe(true);
78
+ if (!delegated.ok)
79
+ return;
80
+ await d.requestDmAccess(a.peerId, delegated.token);
81
+ expect(a.listPendingRoomJoins()).toEqual([]);
82
+ expect(d.listPendingRoomJoins()).toEqual([]);
83
+ }
84
+ finally {
85
+ await d.shutdown();
86
+ await a.shutdown();
87
+ }
88
+ });
89
+ //# sourceMappingURL=dm-send-principal-delegation.integration.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dm-send-principal-delegation.integration.test.js","sourceRoot":"","sources":["../../src/test/dm-send-principal-delegation.integration.test.ts"],"names":[],"mappings":"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"}
@@ -113,5 +113,97 @@ describe("GatewayTrust persistence (agent-comms#186)", () => {
113
113
  const restartedB = new GatewayTrust(slotB);
114
114
  expect(restartedB.list()).toEqual([]);
115
115
  });
116
+ // Principal persistence (agent-comms#187) -- extends #186's own device-only persistence to the second, parallel principal allowlist, per #186's own issue text naming #187 as the one that decides what gets stored.
117
+ it("persists a trusted principal, surviving a restart alongside the bare-device set", () => {
118
+ const slot = tempSlot("pi");
119
+ const first = new GatewayTrust(slot);
120
+ first.add("aabbcc");
121
+ first.addPrincipal("112233");
122
+ const restarted = new GatewayTrust(slot);
123
+ expect(restarted.list()).toEqual(["aabbcc"]);
124
+ expect(restarted.listPrincipals()).toEqual(["112233"]);
125
+ });
126
+ it("persists a principal removal independently of the bare-device set", () => {
127
+ const slot = tempSlot("pi");
128
+ const first = new GatewayTrust(slot);
129
+ first.addPrincipal("112233");
130
+ first.addPrincipal("445566");
131
+ first.removePrincipal("112233");
132
+ const restarted = new GatewayTrust(slot);
133
+ expect(restarted.listPrincipals()).toEqual(["445566"]);
134
+ });
135
+ });
136
+ describe("GatewayTrust -- principal-keyed trust (agent-comms#187)", () => {
137
+ it("trusts no principal by default", () => {
138
+ const trust = new GatewayTrust();
139
+ expect(trust.isTrustedPrincipal("aabbcc")).toBe(false);
140
+ expect(trust.listPrincipals()).toEqual([]);
141
+ });
142
+ it("trusts a principal once added, independently of the bare-device set", () => {
143
+ const trust = new GatewayTrust();
144
+ trust.addPrincipal("AABBCC");
145
+ expect(trust.isTrustedPrincipal("aabbcc")).toBe(true);
146
+ expect(trust.listPrincipals()).toEqual(["aabbcc"]);
147
+ expect(trust.isTrusted("aabbcc")).toBe(false);
148
+ });
149
+ it("normalises hex case for principals the same way it does for bare devices", () => {
150
+ const trust = new GatewayTrust();
151
+ trust.addPrincipal("AaBbCc");
152
+ expect(trust.isTrustedPrincipal("aabbcc")).toBe(true);
153
+ expect(trust.isTrustedPrincipal("AABBCC")).toBe(true);
154
+ });
155
+ it("is idempotent: adding the same principal twice keeps it listed once", () => {
156
+ const trust = new GatewayTrust();
157
+ trust.addPrincipal("aabbcc");
158
+ trust.addPrincipal("AABBCC");
159
+ expect(trust.listPrincipals()).toEqual(["aabbcc"]);
160
+ });
161
+ it("stops trusting a principal once removed", () => {
162
+ const trust = new GatewayTrust();
163
+ trust.addPrincipal("aabbcc");
164
+ trust.removePrincipal("AABBCC");
165
+ expect(trust.isTrustedPrincipal("aabbcc")).toBe(false);
166
+ expect(trust.listPrincipals()).toEqual([]);
167
+ });
168
+ it("removing a principal that was never trusted is a safe no-op", () => {
169
+ const trust = new GatewayTrust();
170
+ expect(() => {
171
+ trust.removePrincipal("aabbcc");
172
+ }).not.toThrow();
173
+ expect(trust.listPrincipals()).toEqual([]);
174
+ });
175
+ it("hasAny becomes true once a principal is trusted, even with no bare device ever trusted", () => {
176
+ const trust = new GatewayTrust();
177
+ expect(trust.hasAny()).toBe(false);
178
+ trust.addPrincipal("aabbcc");
179
+ expect(trust.hasAny()).toBe(true);
180
+ });
181
+ it("hasAny falls back to false once both the device and principal sets are empty again", () => {
182
+ const trust = new GatewayTrust();
183
+ trust.addPrincipal("aabbcc");
184
+ trust.removePrincipal("aabbcc");
185
+ expect(trust.hasAny()).toBe(false);
186
+ });
187
+ describe("isTrustedFor -- deciding trust from a verified token's own bearer and chain root", () => {
188
+ it("passes a bearer that is itself directly trusted, regardless of its chain root", () => {
189
+ const trust = new GatewayTrust();
190
+ trust.add("aabbcc");
191
+ expect(trust.isTrustedFor("aabbcc", "ffffff")).toBe(true);
192
+ });
193
+ it("passes a bearer whose chain roots at a trusted principal, even though the bearer itself was never individually trusted", () => {
194
+ const trust = new GatewayTrust();
195
+ trust.addPrincipal("ffffff");
196
+ expect(trust.isTrustedFor("aabbcc", "ffffff")).toBe(true);
197
+ });
198
+ it("refuses a bearer that is neither directly trusted nor rooted at a trusted principal", () => {
199
+ const trust = new GatewayTrust();
200
+ expect(trust.isTrustedFor("aabbcc", "ffffff")).toBe(false);
201
+ });
202
+ it("is case-insensitive on both the bearer and the chain-root hex", () => {
203
+ const trust = new GatewayTrust();
204
+ trust.addPrincipal("FFFFFF");
205
+ expect(trust.isTrustedFor("AABBCC", "ffffff")).toBe(true);
206
+ });
207
+ });
116
208
  });
117
209
  //# sourceMappingURL=gateway-trust.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"gateway-trust.test.js","sourceRoot":"","sources":["../../src/test/gateway-trust.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gateway-trust.test.js","sourceRoot":"","sources":["../../src/test/gateway-trust.test.ts"],"names":[],"mappings":"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"}
@@ -246,35 +246,59 @@ test("deleteGroupToken is a no-op when nothing was saved for that group path", (
246
246
  });
247
247
  test("loadGatewayTrust is empty for a slot that has never saved a trusted set", () => {
248
248
  const { slot } = tempSlot("pi");
249
- expect(loadGatewayTrust(slot)).toEqual([]);
249
+ expect(loadGatewayTrust(slot)).toEqual({ devices: [], principals: [] });
250
250
  });
251
251
  test("loadGatewayTrust does not require an identity to have been created first, unlike loadRoomTokens/loadGroupTokens", () => {
252
252
  const { slot } = tempSlot("pi");
253
253
  expect(() => {
254
- saveGatewayTrust(slot, ["aabbcc"]);
254
+ saveGatewayTrust(slot, ["aabbcc"], []);
255
255
  }).not.toThrow();
256
- expect(loadGatewayTrust(slot)).toEqual(["aabbcc"]);
256
+ expect(loadGatewayTrust(slot)).toEqual({
257
+ devices: ["aabbcc"],
258
+ principals: [],
259
+ });
257
260
  });
258
- test("saveGatewayTrust persists the trusted set, loadGatewayTrust reloads the same list", () => {
261
+ test("saveGatewayTrust persists the trusted device and principal sets, loadGatewayTrust reloads the same lists", () => {
259
262
  const { slot } = tempSlot("pi");
260
- saveGatewayTrust(slot, ["aabbcc", "ddeeff"]);
261
- expect(loadGatewayTrust(slot)).toEqual(["aabbcc", "ddeeff"]);
263
+ saveGatewayTrust(slot, ["aabbcc", "ddeeff"], ["112233"]);
264
+ expect(loadGatewayTrust(slot)).toEqual({
265
+ devices: ["aabbcc", "ddeeff"],
266
+ principals: ["112233"],
267
+ });
262
268
  });
263
- test("saveGatewayTrust overwrites the previously saved set rather than merging with it", () => {
269
+ test("saveGatewayTrust overwrites the previously saved sets rather than merging with them", () => {
264
270
  const { slot } = tempSlot("pi");
265
- saveGatewayTrust(slot, ["aabbcc", "ddeeff"]);
266
- saveGatewayTrust(slot, ["112233"]);
267
- expect(loadGatewayTrust(slot)).toEqual(["112233"]);
271
+ saveGatewayTrust(slot, ["aabbcc", "ddeeff"], ["112233"]);
272
+ saveGatewayTrust(slot, ["112233"], ["445566"]);
273
+ expect(loadGatewayTrust(slot)).toEqual({
274
+ devices: ["112233"],
275
+ principals: ["445566"],
276
+ });
268
277
  });
269
- test("saveGatewayTrust persists an empty set, clearing whatever was saved before", () => {
278
+ test("saveGatewayTrust persists empty sets, clearing whatever was saved before", () => {
270
279
  const { slot } = tempSlot("pi");
271
- saveGatewayTrust(slot, ["aabbcc"]);
272
- saveGatewayTrust(slot, []);
273
- expect(loadGatewayTrust(slot)).toEqual([]);
280
+ saveGatewayTrust(slot, ["aabbcc"], ["112233"]);
281
+ saveGatewayTrust(slot, [], []);
282
+ expect(loadGatewayTrust(slot)).toEqual({ devices: [], principals: [] });
283
+ });
284
+ test("loadGatewayTrust reads a pre-agent-comms#187 bare-array file as devices-only, with no principals", () => {
285
+ const { slot, dir } = tempSlot("pi");
286
+ // Create the real gateway-trust file at its actual path first (its exact slugified name is an implementation detail), then overwrite its content with the bare-array shape every file written before principal-keyed trust existed actually used.
287
+ saveGatewayTrust(slot, [], []);
288
+ const file = fs
289
+ .readdirSync(dir)
290
+ .find((f) => f.startsWith("gateway-trust-") && f.endsWith(".json"));
291
+ if (file === undefined)
292
+ throw new Error("expected a gateway-trust file");
293
+ fs.writeFileSync(path.join(dir, file), `${JSON.stringify(["aabbcc", "ddeeff"])}\n`);
294
+ expect(loadGatewayTrust(slot)).toEqual({
295
+ devices: ["aabbcc", "ddeeff"],
296
+ principals: [],
297
+ });
274
298
  });
275
299
  test("the gateway trust file is written with owner-only permissions", () => {
276
300
  const { slot, dir } = tempSlot("pi");
277
- saveGatewayTrust(slot, ["aabbcc"]);
301
+ saveGatewayTrust(slot, ["aabbcc"], []);
278
302
  const file = fs
279
303
  .readdirSync(dir)
280
304
  .find((f) => f.startsWith("gateway-trust-") && f.endsWith(".json"));
@@ -286,7 +310,7 @@ test("the gateway trust file is written with owner-only permissions", () => {
286
310
  });
287
311
  test("the gateway trust file is a sibling of the identity file, distinct per (harness, cwd)", () => {
288
312
  const { slot, dir } = tempSlot("pi");
289
- saveGatewayTrust(slot, ["aabbcc"]);
313
+ saveGatewayTrust(slot, ["aabbcc"], []);
290
314
  const file = fs
291
315
  .readdirSync(dir)
292
316
  .find((f) => f.startsWith("gateway-trust-") && f.endsWith(".json"));
@@ -298,13 +322,13 @@ test("the gateway trust file is a sibling of the identity file, distinct per (ha
298
322
  });
299
323
  test("loadGatewayTrust returns empty for a slot whose gateway trust file is corrupt", () => {
300
324
  const { slot, dir } = tempSlot("pi");
301
- saveGatewayTrust(slot, ["aabbcc"]);
325
+ saveGatewayTrust(slot, ["aabbcc"], []);
302
326
  const file = fs
303
327
  .readdirSync(dir)
304
328
  .find((f) => f.startsWith("gateway-trust-") && f.endsWith(".json"));
305
329
  if (file === undefined)
306
330
  throw new Error("expected a gateway-trust file");
307
331
  fs.writeFileSync(path.join(dir, file), "not valid json{{{");
308
- expect(loadGatewayTrust(slot)).toEqual([]);
332
+ expect(loadGatewayTrust(slot)).toEqual({ devices: [], principals: [] });
309
333
  });
310
334
  //# sourceMappingURL=identity-store.test.js.map