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 <noreply@anthropic.com>
This commit is contained in:
Jeff Emmett 2026-03-11 20:16:17 -07:00
parent 71b2acd47b
commit 845704d5a4
1 changed files with 20 additions and 23 deletions

View File

@ -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) {