From 845704d5a496bf33b03f182bcc6a91fb1cbc4a61 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Wed, 11 Mar 2026 20:16:17 -0700 Subject: [PATCH] fix(rnetwork): use per-space scoping for trust data (not global) rNetwork declares defaultScope='global' for CRM data, but trust/ delegation data is per-space. The effectiveSpace middleware resolved to 'global' causing all EncryptID queries to pass space=global, returning empty results. Fixed by using URL space param directly for trust-related endpoints. Also fixed delegations proxy to use /api/delegations/space endpoint. Co-Authored-By: Claude Opus 4.6 --- modules/rnetwork/mod.ts | 43 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/modules/rnetwork/mod.ts b/modules/rnetwork/mod.ts index 4274ac1..c3e9705 100644 --- a/modules/rnetwork/mod.ts +++ b/modules/rnetwork/mod.ts @@ -126,19 +126,22 @@ routes.get("/api/companies", async (c) => { return c.json({ companies }); }); +// Helper: resolve the trust/identity space (always per-space, ignoring module's global scoping) +function getTrustSpace(c: any): string { + return c.req.query("space") || c.req.param("space") || "demo"; +} + +const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; + // ── API: Users — EncryptID user directory with trust metadata ── routes.get("/api/users", async (c) => { - const space = c.req.param("space") || "demo"; - const dataSpace = (c.get("effectiveSpace" as any) as string) || space; - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; - + const space = getTrustSpace(c); try { - const res = await fetch(`${ENCRYPTID_URL}/api/users/directory?space=${encodeURIComponent(dataSpace)}`, { + const res = await fetch(`${ENCRYPTID_URL}/api/users/directory?space=${encodeURIComponent(space)}`, { signal: AbortSignal.timeout(5000), }); if (!res.ok) return c.json({ users: [], error: "User directory unavailable" }); - const data = await res.json() as { users: unknown[] }; - return c.json(data); + return c.json(await res.json()); } catch { return c.json({ users: [], error: "EncryptID unreachable" }); } @@ -146,14 +149,11 @@ routes.get("/api/users", async (c) => { // ── API: Trust scores for graph visualization ── routes.get("/api/trust", async (c) => { - const space = c.req.param("space") || "demo"; - const dataSpace = (c.get("effectiveSpace" as any) as string) || space; + const space = getTrustSpace(c); const authority = c.req.query("authority") || "voting"; - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; - try { const res = await fetch( - `${ENCRYPTID_URL}/api/trust/scores?space=${encodeURIComponent(dataSpace)}&authority=${encodeURIComponent(authority)}`, + `${ENCRYPTID_URL}/api/trust/scores?space=${encodeURIComponent(space)}&authority=${encodeURIComponent(authority)}`, { signal: AbortSignal.timeout(5000) }, ); if (!res.ok) return c.json({ scores: [], authority, error: "Trust scores unavailable" }); @@ -165,15 +165,11 @@ routes.get("/api/trust", async (c) => { // ── API: Delegations for graph edges ── routes.get("/api/delegations", async (c) => { - const space = c.req.param("space") || "demo"; - const dataSpace = (c.get("effectiveSpace" as any) as string) || space; + const space = getTrustSpace(c); const authority = c.req.query("authority"); - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; - - // Proxy delegation data for the space - uses internal API try { - const url = new URL(`${ENCRYPTID_URL}/api/trust/scores`); - url.searchParams.set("space", dataSpace); + const url = new URL(`${ENCRYPTID_URL}/api/delegations/space`); + url.searchParams.set("space", space); if (authority) url.searchParams.set("authority", authority); const res = await fetch(url, { signal: AbortSignal.timeout(5000) }); if (!res.ok) return c.json({ delegations: [], error: "Delegations unavailable" }); @@ -254,13 +250,14 @@ routes.get("/api/graph", async (c) => { } // If trust=true, merge EncryptID user nodes + delegation edges + // Trust data uses per-space scoping (not module's global scoping) if (includeTrust) { - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; + const trustSpace = c.req.param("space") || "demo"; try { const [usersRes, scoresRes, delegRes] = await Promise.all([ - fetch(`${ENCRYPTID_URL}/api/users/directory?space=${encodeURIComponent(dataSpace)}`, { signal: AbortSignal.timeout(5000) }), - fetch(`${ENCRYPTID_URL}/api/trust/scores?space=${encodeURIComponent(dataSpace)}&authority=${encodeURIComponent(authority)}`, { signal: AbortSignal.timeout(5000) }), - fetch(`${ENCRYPTID_URL}/api/delegations/space?space=${encodeURIComponent(dataSpace)}&authority=${encodeURIComponent(authority)}`, { signal: AbortSignal.timeout(5000) }), + fetch(`${ENCRYPTID_URL}/api/users/directory?space=${encodeURIComponent(trustSpace)}`, { signal: AbortSignal.timeout(5000) }), + fetch(`${ENCRYPTID_URL}/api/trust/scores?space=${encodeURIComponent(trustSpace)}&authority=${encodeURIComponent(authority)}`, { signal: AbortSignal.timeout(5000) }), + fetch(`${ENCRYPTID_URL}/api/delegations/space?space=${encodeURIComponent(trustSpace)}&authority=${encodeURIComponent(authority)}`, { signal: AbortSignal.timeout(5000) }), ]); if (usersRes.ok) {