diff --git a/dist/fabric/src/fabric-client.js b/dist/fabric/src/fabric-client.js index 1cde727..e65c59e 100644 --- a/dist/fabric/src/fabric-client.js +++ b/dist/fabric/src/fabric-client.js @@ -23,12 +23,13 @@ export class FabricClient { } // Generic JSON request (GET/PUT/PATCH/DELETE). Empty 2xx body -> null // (Fabric returns an empty body when a channel has no canvas). - async req(method, url, auth, body) { + async req(method, url, auth, body, extraHeaders) { const res = await fetch(url, { method, headers: { ...(body !== undefined ? { 'content-type': 'application/json' } : {}), ...(auth ? { authorization: `Bearer ${auth}` } : {}), + ...(extraHeaders ?? {}), }, body: body !== undefined ? JSON.stringify(body) : undefined, }); @@ -75,7 +76,11 @@ export class FabricClient { // full replace). The frontend GETs it for `/` autocomplete; execution // still flows as a normal / message into OpenClaw's command system. syncCommands(guildEndpoint, guildToken, commands) { - return this.req('PUT', `${guildEndpoint}/api/commands`, guildToken, { commands }); + // Guild C-2: when the operator sets a shared sync key on both sides + // (FABRIC_COMMANDS_SYNC_KEY here / FABRIC_BACKEND_GUILD_COMMANDS_SYNC_KEY + // on the guild), the catalog write is restricted to this plugin. + const key = process.env.FABRIC_COMMANDS_SYNC_KEY; + return this.req('PUT', `${guildEndpoint}/api/commands`, guildToken, { commands }, key ? { 'x-commands-sync-key': key } : undefined); } // [{ userId, bypass }] — bypass is true only for discuss/work bypass-list channelMembers(guildEndpoint, guildToken, channelId) { diff --git a/src/fabric-client.ts b/src/fabric-client.ts index aa1518f..486335a 100644 --- a/src/fabric-client.ts +++ b/src/fabric-client.ts @@ -36,12 +36,14 @@ export class FabricClient { url: string, auth?: string, body?: unknown, + extraHeaders?: Record, ): Promise { const res = await fetch(url, { method, headers: { ...(body !== undefined ? { 'content-type': 'application/json' } : {}), ...(auth ? { authorization: `Bearer ${auth}` } : {}), + ...(extraHeaders ?? {}), }, body: body !== undefined ? JSON.stringify(body) : undefined, }); @@ -123,7 +125,17 @@ export class FabricClient { guildToken: string, commands: unknown[], ): Promise { - return this.req('PUT', `${guildEndpoint}/api/commands`, guildToken, { commands }); + // Guild C-2: when the operator sets a shared sync key on both sides + // (FABRIC_COMMANDS_SYNC_KEY here / FABRIC_BACKEND_GUILD_COMMANDS_SYNC_KEY + // on the guild), the catalog write is restricted to this plugin. + const key = process.env.FABRIC_COMMANDS_SYNC_KEY; + return this.req( + 'PUT', + `${guildEndpoint}/api/commands`, + guildToken, + { commands }, + key ? { 'x-commands-sync-key': key } : undefined, + ); } // [{ userId, bypass }] — bypass is true only for discuss/work bypass-list