@sleep2agi/commhub-server 0.9.0-preview.151 → 0.9.0-preview.152

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sleep2agi/commhub-server",
3
- "version": "0.9.0-preview.151",
3
+ "version": "0.9.0-preview.152",
4
4
  "description": "CommHub Server — AI Agent communication hub with MCP protocol, multi-network isolation, user auth, and MCP tools (17 collaboration-core + node/provider ops tools; authoritative list: docs-site/docs/api/mcp-tools.md).",
5
5
  "type": "module",
6
6
  "main": "src/index.ts",
@@ -107,6 +107,16 @@ describe("#993 — network rules storage + CAS write", () => {
107
107
  expect(r.body.error).toBe("rules_too_large");
108
108
  });
109
109
 
110
+ test("a node token cannot read another network's rules", async () => {
111
+ // The node token belongs to a hub admin (that is how it was minted), so the
112
+ // hubAdmin branch alone would have allowed it. A node stays inside its network.
113
+ const other = register(`nr_net2_${Date.now()}`, "OtherPw123Aa!", undefined, "net2");
114
+ expect(other.ok).toBe(true);
115
+ const r = await send(nodeToken, "GET", `/api/networks/${other.network_id}/rules`);
116
+ expect(r.status).toBe(403);
117
+ expect(r.body.error).toBe("not_a_member");
118
+ });
119
+
110
120
  test("a non-member cannot read", async () => {
111
121
  const other = register(`nr_other_${Date.now()}`, "OtherPw123Aa!", undefined, "other");
112
122
  expect(other.ok).toBe(true);
package/src/server.ts CHANGED
@@ -1903,6 +1903,12 @@ return Bun.serve({
1903
1903
  const role = getUserNetworkRole(resolved.user.user_id, netId);
1904
1904
  ensureNetworkRulesOnce(db);
1905
1905
  if (req.method === "GET") {
1906
+ // A node token resolves to the human who created it, which may be a hub
1907
+ // admin — that must not turn a node into a reader of *every* network's
1908
+ // rules. A node token is confined to its own network.
1909
+ if (resolved.networkId && resolved.networkId !== netId) {
1910
+ return withCors(req, Response.json({ ok: false, error: "not_a_member" }, { status: 403 }));
1911
+ }
1906
1912
  // Reading is for anyone in the network: the rules are what the nodes obey.
1907
1913
  if (!hubAdmin && !role) return withCors(req, Response.json({ ok: false, error: "not_a_member" }, { status: 403 }));
1908
1914
  return withCors(req, Response.json({ ok: true, rules: readNetworkRules(db, netId) }));