From 97636235bfde260c746f1c0e73087b8a81fc4915 Mon Sep 17 00:00:00 2001 From: Jeff Emmett Date: Mon, 16 Mar 2026 20:50:13 -0700 Subject: [PATCH] fix(spaces): use correct EncryptID internal URL for member operations The spaces module was defaulting to http://localhost:3000 for EncryptID API calls, which resolves to the rspace container itself (both run on port 3000). Changed to http://encryptid:3000 matching server/index.ts. Also improved error surfacing in /members/add endpoint. Co-Authored-By: Claude Opus 4.6 --- server/spaces.ts | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/server/spaces.ts b/server/spaces.ts index 8c5b0c3..3a52907 100644 --- a/server/spaces.ts +++ b/server/spaces.ts @@ -70,6 +70,8 @@ import { syncServer } from "./sync-instance"; import { seedTemplateShapes } from "./seed-template"; import { notify, notifySpaceAdmins } from "./notification-service"; +const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://encryptid:3000"; + // ── Role types and helpers ── export type SpaceRoleString = 'viewer' | 'member' | 'moderator' | 'admin'; @@ -2122,7 +2124,7 @@ spaces.post("/:slug/invite", async (c) => { const expiresAt = Date.now() + 7 * 24 * 60 * 60 * 1000; // 7 days // Store invite (call EncryptID API internally) - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://localhost:3000"; + try { await fetch(`${ENCRYPTID_URL}/api/spaces/${slug}/invites`, { method: "POST", @@ -2192,12 +2194,16 @@ spaces.post("/:slug/members/add", async (c) => { } // Look up user via EncryptID - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://localhost:3000"; + const lookupRes = await fetch(`${ENCRYPTID_URL}/api/users/lookup?username=${encodeURIComponent(body.username)}`, { headers: { "Authorization": `Bearer ${token}` }, }); if (!lookupRes.ok) { - return c.json({ error: "User not found" }, 404); + const errBody = await lookupRes.json().catch(() => ({})) as Record; + if (lookupRes.status === 404) { + return c.json({ error: `User "${body.username}" not found` }, 404); + } + return c.json({ error: (errBody.error as string) || "User lookup failed" }, lookupRes.status as any); } const user = await lookupRes.json() as { did: string; username: string; displayName: string }; @@ -2251,7 +2257,7 @@ spaces.post("/:slug/invite/accept", async (c) => { if (!body.inviteToken) return c.json({ error: "inviteToken is required" }, 400); // Accept via EncryptID API - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://localhost:3000"; + const acceptRes = await fetch(`${ENCRYPTID_URL}/api/invites/${body.inviteToken}/accept`, { method: "POST", headers: { "Authorization": `Bearer ${token}` }, @@ -2292,7 +2298,7 @@ spaces.get("/:slug/invites", async (c) => { } // Fetch from EncryptID - const ENCRYPTID_URL = process.env.ENCRYPTID_INTERNAL_URL || "http://localhost:3000"; + try { const res = await fetch(`${ENCRYPTID_URL}/api/spaces/${slug}/invites`, { headers: { "Authorization": `Bearer ${token}` },