@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 +1 -1
- package/src/network-rules-http.test.ts +10 -0
- package/src/server.ts +6 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sleep2agi/commhub-server",
|
|
3
|
-
"version": "0.9.0-preview.
|
|
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) }));
|