fastgrc-openclaw 1.0.29 → 1.0.30

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/dist/bin.js CHANGED
@@ -95,26 +95,9 @@ args: ${JSON.stringify(args)}`;
95
95
 
96
96
  // src/plugin.ts
97
97
  var net = __toESM(require("net"));
98
- var crypto = __toESM(require("crypto"));
99
98
  var fs2 = __toESM(require("fs"));
100
99
  var os2 = __toESM(require("os"));
101
100
  var path2 = __toESM(require("path"));
102
- function sign(payload, token) {
103
- const nonce = crypto.randomBytes(16).toString("hex");
104
- const ts = Math.floor(Date.now() / 1e3).toString();
105
- const body = JSON.stringify(payload);
106
- const mac = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${ts}:${body}`).digest("hex");
107
- return { ...payload, nonce, timestamp: ts, hmac: mac };
108
- }
109
- function verifyHmac(req, token) {
110
- try {
111
- const { nonce, timestamp, hmac, ...rest } = req;
112
- const expected = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${timestamp}:${JSON.stringify(rest)}`).digest("hex");
113
- return hmac === expected;
114
- } catch {
115
- return false;
116
- }
117
- }
118
101
  function readExecApprovalsConfig() {
119
102
  const cfgPath = path2.join(os2.homedir(), ".openclaw", "exec-approvals.json");
120
103
  try {
@@ -123,53 +106,77 @@ function readExecApprovalsConfig() {
123
106
  return null;
124
107
  }
125
108
  }
126
- function startExecApprovalsClient(apiKey, policyId, baseUrl) {
109
+ function startExecApprovalsServer(apiKey, policyId, baseUrl) {
127
110
  const cfg = readExecApprovalsConfig();
128
- if (!cfg?.socket?.path || !cfg?.socket?.token) return;
129
- const { path: sockPath, token } = cfg.socket;
130
- function connect() {
131
- const client = net.createConnection(sockPath);
111
+ if (!cfg?.socket?.path || !cfg?.socket?.token) {
112
+ console.warn("[fastgrc] exec-approvals: no socket config found \u2014 webchat execs will not be evaluated");
113
+ return;
114
+ }
115
+ const { path: sockPath, token: configToken } = cfg.socket;
116
+ try {
117
+ fs2.unlinkSync(sockPath);
118
+ } catch {
119
+ }
120
+ const server = net.createServer((conn) => {
132
121
  let buffer = "";
133
- client.on("connect", () => {
134
- console.log("[fastgrc] exec-approvals socket connected");
135
- });
136
- client.on("data", async (buf) => {
137
- buffer += buf.toString();
138
- let req;
122
+ conn.on("data", (chunk) => {
123
+ buffer += chunk.toString("utf8");
124
+ const idx = buffer.indexOf("\n");
125
+ if (idx === -1) return;
126
+ const line = buffer.slice(0, idx).trim();
127
+ buffer = "";
128
+ if (!line) {
129
+ conn.destroy();
130
+ return;
131
+ }
132
+ let msg;
139
133
  try {
140
- req = JSON.parse(buffer);
134
+ msg = JSON.parse(line);
141
135
  } catch {
136
+ conn.destroy();
142
137
  return;
143
138
  }
144
- buffer = "";
145
- if (!verifyHmac(req, token)) {
146
- console.warn("[fastgrc] exec-approvals: HMAC verification failed \u2014 ignoring request");
139
+ if (msg.type !== "request" || msg.token !== configToken) {
140
+ conn.destroy();
147
141
  return;
148
142
  }
149
- let decision = "allow-once";
150
- try {
151
- const result = await evaluate({
152
- toolName: "Exec",
153
- args: { command: req.command, rawCommand: req.rawCommand, cwd: req.cwd },
154
- agentId: req.agentId,
155
- apiKey,
156
- policyId,
157
- baseUrl
158
- });
143
+ const req = msg.request ?? {};
144
+ const command = String(req.command ?? req.commandPreview ?? "unknown");
145
+ const agentId = req.agentId || void 0;
146
+ evaluate({
147
+ toolName: "Exec",
148
+ args: { command, cwd: req.cwd },
149
+ agentId,
150
+ apiKey,
151
+ policyId,
152
+ baseUrl
153
+ }).then((result) => {
154
+ let decision = "allow-once";
159
155
  if (result && (result.decision === "block" || result.decision === "require_approval")) {
160
156
  decision = "deny";
161
- const msg = result.policyContext?.matchedRule ? `[fastgrc] exec blocked: [${result.policyContext.matchedRule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`;
162
- console.warn(msg);
157
+ const rule = result.policyContext?.matchedRule;
158
+ console.warn(rule ? `[fastgrc] exec blocked: [${rule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`);
163
159
  }
164
- } catch {
165
- }
166
- const response = sign({ approvalId: req.approvalId, decision }, token);
167
- client.write(JSON.stringify(response));
160
+ conn.write(JSON.stringify({ type: "decision", decision }) + "\n");
161
+ conn.destroy();
162
+ }).catch(() => {
163
+ conn.write(JSON.stringify({ type: "decision", decision: "allow-once" }) + "\n");
164
+ conn.destroy();
165
+ });
168
166
  });
169
- client.on("error", () => setTimeout(connect, 5e3));
170
- client.on("close", () => setTimeout(connect, 5e3));
171
- }
172
- connect();
167
+ conn.on("error", () => {
168
+ });
169
+ });
170
+ server.listen(sockPath, () => {
171
+ try {
172
+ fs2.chmodSync(sockPath, 384);
173
+ } catch {
174
+ }
175
+ console.log(`[fastgrc] exec-approvals server listening on ${sockPath}`);
176
+ });
177
+ server.on("error", (err) => {
178
+ console.warn(`[fastgrc] exec-approvals server error: ${err.message}`);
179
+ });
173
180
  }
174
181
 
175
182
  // src/bin.ts
@@ -420,7 +427,7 @@ if (cmd === "serve-approvals") {
420
427
  const baseUrl = process.env.FASTGRC_BASE_URL ?? "https://app.fastgrc.ai";
421
428
  process.stdout.write(`[fastgrc] serve-approvals running \u2014 listening on ${cfg.socket.path}
422
429
  `);
423
- startExecApprovalsClient(apiKey, policyId, baseUrl);
430
+ startExecApprovalsServer(apiKey, policyId, baseUrl);
424
431
  }
425
432
  if (cmd === "uninstall") {
426
433
  const targetDir = arg || process.cwd();
package/dist/bin.mjs CHANGED
@@ -72,26 +72,9 @@ args: ${JSON.stringify(args)}`;
72
72
 
73
73
  // src/plugin.ts
74
74
  import * as net from "net";
75
- import * as crypto from "crypto";
76
75
  import * as fs2 from "fs";
77
76
  import * as os2 from "os";
78
77
  import * as path2 from "path";
79
- function sign(payload, token) {
80
- const nonce = crypto.randomBytes(16).toString("hex");
81
- const ts = Math.floor(Date.now() / 1e3).toString();
82
- const body = JSON.stringify(payload);
83
- const mac = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${ts}:${body}`).digest("hex");
84
- return { ...payload, nonce, timestamp: ts, hmac: mac };
85
- }
86
- function verifyHmac(req, token) {
87
- try {
88
- const { nonce, timestamp, hmac, ...rest } = req;
89
- const expected = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${timestamp}:${JSON.stringify(rest)}`).digest("hex");
90
- return hmac === expected;
91
- } catch {
92
- return false;
93
- }
94
- }
95
78
  function readExecApprovalsConfig() {
96
79
  const cfgPath = path2.join(os2.homedir(), ".openclaw", "exec-approvals.json");
97
80
  try {
@@ -100,53 +83,77 @@ function readExecApprovalsConfig() {
100
83
  return null;
101
84
  }
102
85
  }
103
- function startExecApprovalsClient(apiKey, policyId, baseUrl) {
86
+ function startExecApprovalsServer(apiKey, policyId, baseUrl) {
104
87
  const cfg = readExecApprovalsConfig();
105
- if (!cfg?.socket?.path || !cfg?.socket?.token) return;
106
- const { path: sockPath, token } = cfg.socket;
107
- function connect() {
108
- const client = net.createConnection(sockPath);
88
+ if (!cfg?.socket?.path || !cfg?.socket?.token) {
89
+ console.warn("[fastgrc] exec-approvals: no socket config found \u2014 webchat execs will not be evaluated");
90
+ return;
91
+ }
92
+ const { path: sockPath, token: configToken } = cfg.socket;
93
+ try {
94
+ fs2.unlinkSync(sockPath);
95
+ } catch {
96
+ }
97
+ const server = net.createServer((conn) => {
109
98
  let buffer = "";
110
- client.on("connect", () => {
111
- console.log("[fastgrc] exec-approvals socket connected");
112
- });
113
- client.on("data", async (buf) => {
114
- buffer += buf.toString();
115
- let req;
99
+ conn.on("data", (chunk) => {
100
+ buffer += chunk.toString("utf8");
101
+ const idx = buffer.indexOf("\n");
102
+ if (idx === -1) return;
103
+ const line = buffer.slice(0, idx).trim();
104
+ buffer = "";
105
+ if (!line) {
106
+ conn.destroy();
107
+ return;
108
+ }
109
+ let msg;
116
110
  try {
117
- req = JSON.parse(buffer);
111
+ msg = JSON.parse(line);
118
112
  } catch {
113
+ conn.destroy();
119
114
  return;
120
115
  }
121
- buffer = "";
122
- if (!verifyHmac(req, token)) {
123
- console.warn("[fastgrc] exec-approvals: HMAC verification failed \u2014 ignoring request");
116
+ if (msg.type !== "request" || msg.token !== configToken) {
117
+ conn.destroy();
124
118
  return;
125
119
  }
126
- let decision = "allow-once";
127
- try {
128
- const result = await evaluate({
129
- toolName: "Exec",
130
- args: { command: req.command, rawCommand: req.rawCommand, cwd: req.cwd },
131
- agentId: req.agentId,
132
- apiKey,
133
- policyId,
134
- baseUrl
135
- });
120
+ const req = msg.request ?? {};
121
+ const command = String(req.command ?? req.commandPreview ?? "unknown");
122
+ const agentId = req.agentId || void 0;
123
+ evaluate({
124
+ toolName: "Exec",
125
+ args: { command, cwd: req.cwd },
126
+ agentId,
127
+ apiKey,
128
+ policyId,
129
+ baseUrl
130
+ }).then((result) => {
131
+ let decision = "allow-once";
136
132
  if (result && (result.decision === "block" || result.decision === "require_approval")) {
137
133
  decision = "deny";
138
- const msg = result.policyContext?.matchedRule ? `[fastgrc] exec blocked: [${result.policyContext.matchedRule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`;
139
- console.warn(msg);
134
+ const rule = result.policyContext?.matchedRule;
135
+ console.warn(rule ? `[fastgrc] exec blocked: [${rule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`);
140
136
  }
141
- } catch {
142
- }
143
- const response = sign({ approvalId: req.approvalId, decision }, token);
144
- client.write(JSON.stringify(response));
137
+ conn.write(JSON.stringify({ type: "decision", decision }) + "\n");
138
+ conn.destroy();
139
+ }).catch(() => {
140
+ conn.write(JSON.stringify({ type: "decision", decision: "allow-once" }) + "\n");
141
+ conn.destroy();
142
+ });
145
143
  });
146
- client.on("error", () => setTimeout(connect, 5e3));
147
- client.on("close", () => setTimeout(connect, 5e3));
148
- }
149
- connect();
144
+ conn.on("error", () => {
145
+ });
146
+ });
147
+ server.listen(sockPath, () => {
148
+ try {
149
+ fs2.chmodSync(sockPath, 384);
150
+ } catch {
151
+ }
152
+ console.log(`[fastgrc] exec-approvals server listening on ${sockPath}`);
153
+ });
154
+ server.on("error", (err) => {
155
+ console.warn(`[fastgrc] exec-approvals server error: ${err.message}`);
156
+ });
150
157
  }
151
158
 
152
159
  // src/bin.ts
@@ -397,7 +404,7 @@ if (cmd === "serve-approvals") {
397
404
  const baseUrl = process.env.FASTGRC_BASE_URL ?? "https://app.fastgrc.ai";
398
405
  process.stdout.write(`[fastgrc] serve-approvals running \u2014 listening on ${cfg.socket.path}
399
406
  `);
400
- startExecApprovalsClient(apiKey, policyId, baseUrl);
407
+ startExecApprovalsServer(apiKey, policyId, baseUrl);
401
408
  }
402
409
  if (cmd === "uninstall") {
403
410
  const targetDir = arg || process.cwd();
package/dist/plugin.d.mts CHANGED
@@ -5,7 +5,7 @@ interface ExecApprovalsConfig {
5
5
  };
6
6
  }
7
7
  declare function readExecApprovalsConfig(): ExecApprovalsConfig | null;
8
- declare function startExecApprovalsClient(apiKey: string, policyId?: string, baseUrl?: string): void;
8
+ declare function startExecApprovalsServer(apiKey: string, policyId?: string, baseUrl?: string): void;
9
9
  declare const pluginEntry: {
10
10
  id: string;
11
11
  name: string;
@@ -13,4 +13,4 @@ declare const pluginEntry: {
13
13
  register(api: any): void;
14
14
  };
15
15
 
16
- export { pluginEntry as default, readExecApprovalsConfig, startExecApprovalsClient };
16
+ export { pluginEntry as default, readExecApprovalsConfig, startExecApprovalsServer };
package/dist/plugin.d.ts CHANGED
@@ -5,7 +5,7 @@ interface ExecApprovalsConfig {
5
5
  };
6
6
  }
7
7
  declare function readExecApprovalsConfig(): ExecApprovalsConfig | null;
8
- declare function startExecApprovalsClient(apiKey: string, policyId?: string, baseUrl?: string): void;
8
+ declare function startExecApprovalsServer(apiKey: string, policyId?: string, baseUrl?: string): void;
9
9
  declare const pluginEntry: {
10
10
  id: string;
11
11
  name: string;
@@ -13,4 +13,4 @@ declare const pluginEntry: {
13
13
  register(api: any): void;
14
14
  };
15
15
 
16
- export { pluginEntry as default, readExecApprovalsConfig, startExecApprovalsClient };
16
+ export { pluginEntry as default, readExecApprovalsConfig, startExecApprovalsServer };
package/dist/plugin.js CHANGED
@@ -32,11 +32,10 @@ var plugin_exports = {};
32
32
  __export(plugin_exports, {
33
33
  default: () => plugin_default,
34
34
  readExecApprovalsConfig: () => readExecApprovalsConfig,
35
- startExecApprovalsClient: () => startExecApprovalsClient
35
+ startExecApprovalsServer: () => startExecApprovalsServer
36
36
  });
37
37
  module.exports = __toCommonJS(plugin_exports);
38
38
  var net = __toESM(require("net"));
39
- var crypto = __toESM(require("crypto"));
40
39
  var fs2 = __toESM(require("fs"));
41
40
  var os2 = __toESM(require("os"));
42
41
  var path2 = __toESM(require("path"));
@@ -121,22 +120,6 @@ args: ${JSON.stringify(args)}`;
121
120
  // src/plugin.ts
122
121
  var DEFAULT_BASE_URL2 = "https://app.fastgrc.ai";
123
122
  var DEFAULT_TIMEOUT_MS2 = 3e3;
124
- function sign(payload, token) {
125
- const nonce = crypto.randomBytes(16).toString("hex");
126
- const ts = Math.floor(Date.now() / 1e3).toString();
127
- const body = JSON.stringify(payload);
128
- const mac = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${ts}:${body}`).digest("hex");
129
- return { ...payload, nonce, timestamp: ts, hmac: mac };
130
- }
131
- function verifyHmac(req, token) {
132
- try {
133
- const { nonce, timestamp, hmac, ...rest } = req;
134
- const expected = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${timestamp}:${JSON.stringify(rest)}`).digest("hex");
135
- return hmac === expected;
136
- } catch {
137
- return false;
138
- }
139
- }
140
123
  function readExecApprovalsConfig() {
141
124
  const cfgPath = path2.join(os2.homedir(), ".openclaw", "exec-approvals.json");
142
125
  try {
@@ -145,53 +128,77 @@ function readExecApprovalsConfig() {
145
128
  return null;
146
129
  }
147
130
  }
148
- function startExecApprovalsClient(apiKey, policyId, baseUrl) {
131
+ function startExecApprovalsServer(apiKey, policyId, baseUrl) {
149
132
  const cfg = readExecApprovalsConfig();
150
- if (!cfg?.socket?.path || !cfg?.socket?.token) return;
151
- const { path: sockPath, token } = cfg.socket;
152
- function connect() {
153
- const client = net.createConnection(sockPath);
133
+ if (!cfg?.socket?.path || !cfg?.socket?.token) {
134
+ console.warn("[fastgrc] exec-approvals: no socket config found \u2014 webchat execs will not be evaluated");
135
+ return;
136
+ }
137
+ const { path: sockPath, token: configToken } = cfg.socket;
138
+ try {
139
+ fs2.unlinkSync(sockPath);
140
+ } catch {
141
+ }
142
+ const server = net.createServer((conn) => {
154
143
  let buffer = "";
155
- client.on("connect", () => {
156
- console.log("[fastgrc] exec-approvals socket connected");
157
- });
158
- client.on("data", async (buf) => {
159
- buffer += buf.toString();
160
- let req;
144
+ conn.on("data", (chunk) => {
145
+ buffer += chunk.toString("utf8");
146
+ const idx = buffer.indexOf("\n");
147
+ if (idx === -1) return;
148
+ const line = buffer.slice(0, idx).trim();
149
+ buffer = "";
150
+ if (!line) {
151
+ conn.destroy();
152
+ return;
153
+ }
154
+ let msg;
161
155
  try {
162
- req = JSON.parse(buffer);
156
+ msg = JSON.parse(line);
163
157
  } catch {
158
+ conn.destroy();
164
159
  return;
165
160
  }
166
- buffer = "";
167
- if (!verifyHmac(req, token)) {
168
- console.warn("[fastgrc] exec-approvals: HMAC verification failed \u2014 ignoring request");
161
+ if (msg.type !== "request" || msg.token !== configToken) {
162
+ conn.destroy();
169
163
  return;
170
164
  }
171
- let decision = "allow-once";
172
- try {
173
- const result = await evaluate({
174
- toolName: "Exec",
175
- args: { command: req.command, rawCommand: req.rawCommand, cwd: req.cwd },
176
- agentId: req.agentId,
177
- apiKey,
178
- policyId,
179
- baseUrl
180
- });
165
+ const req = msg.request ?? {};
166
+ const command = String(req.command ?? req.commandPreview ?? "unknown");
167
+ const agentId = req.agentId || void 0;
168
+ evaluate({
169
+ toolName: "Exec",
170
+ args: { command, cwd: req.cwd },
171
+ agentId,
172
+ apiKey,
173
+ policyId,
174
+ baseUrl
175
+ }).then((result) => {
176
+ let decision = "allow-once";
181
177
  if (result && (result.decision === "block" || result.decision === "require_approval")) {
182
178
  decision = "deny";
183
- const msg = result.policyContext?.matchedRule ? `[fastgrc] exec blocked: [${result.policyContext.matchedRule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`;
184
- console.warn(msg);
179
+ const rule = result.policyContext?.matchedRule;
180
+ console.warn(rule ? `[fastgrc] exec blocked: [${rule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`);
185
181
  }
186
- } catch {
187
- }
188
- const response = sign({ approvalId: req.approvalId, decision }, token);
189
- client.write(JSON.stringify(response));
182
+ conn.write(JSON.stringify({ type: "decision", decision }) + "\n");
183
+ conn.destroy();
184
+ }).catch(() => {
185
+ conn.write(JSON.stringify({ type: "decision", decision: "allow-once" }) + "\n");
186
+ conn.destroy();
187
+ });
190
188
  });
191
- client.on("error", () => setTimeout(connect, 5e3));
192
- client.on("close", () => setTimeout(connect, 5e3));
193
- }
194
- connect();
189
+ conn.on("error", () => {
190
+ });
191
+ });
192
+ server.listen(sockPath, () => {
193
+ try {
194
+ fs2.chmodSync(sockPath, 384);
195
+ } catch {
196
+ }
197
+ console.log(`[fastgrc] exec-approvals server listening on ${sockPath}`);
198
+ });
199
+ server.on("error", (err) => {
200
+ console.warn(`[fastgrc] exec-approvals server error: ${err.message}`);
201
+ });
195
202
  }
196
203
  var pluginEntry = {
197
204
  id: "fastgrc",
@@ -237,13 +244,13 @@ var pluginEntry = {
237
244
  }
238
245
  return void 0;
239
246
  });
240
- startExecApprovalsClient(apiKey, policyId, DEFAULT_BASE_URL2);
247
+ startExecApprovalsServer(apiKey, policyId, DEFAULT_BASE_URL2);
241
248
  }
242
249
  };
243
250
  var plugin_default = pluginEntry;
244
251
  // Annotate the CommonJS export names for ESM import in node:
245
252
  0 && (module.exports = {
246
253
  readExecApprovalsConfig,
247
- startExecApprovalsClient
254
+ startExecApprovalsServer
248
255
  });
249
256
  module.exports = module.exports.default ?? module.exports;
package/dist/plugin.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  // src/plugin.ts
2
2
  import * as net from "net";
3
- import * as crypto from "crypto";
4
3
  import * as fs2 from "fs";
5
4
  import * as os2 from "os";
6
5
  import * as path2 from "path";
@@ -85,22 +84,6 @@ args: ${JSON.stringify(args)}`;
85
84
  // src/plugin.ts
86
85
  var DEFAULT_BASE_URL2 = "https://app.fastgrc.ai";
87
86
  var DEFAULT_TIMEOUT_MS2 = 3e3;
88
- function sign(payload, token) {
89
- const nonce = crypto.randomBytes(16).toString("hex");
90
- const ts = Math.floor(Date.now() / 1e3).toString();
91
- const body = JSON.stringify(payload);
92
- const mac = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${ts}:${body}`).digest("hex");
93
- return { ...payload, nonce, timestamp: ts, hmac: mac };
94
- }
95
- function verifyHmac(req, token) {
96
- try {
97
- const { nonce, timestamp, hmac, ...rest } = req;
98
- const expected = crypto.createHmac("sha256", Buffer.from(token, "base64")).update(`${nonce}:${timestamp}:${JSON.stringify(rest)}`).digest("hex");
99
- return hmac === expected;
100
- } catch {
101
- return false;
102
- }
103
- }
104
87
  function readExecApprovalsConfig() {
105
88
  const cfgPath = path2.join(os2.homedir(), ".openclaw", "exec-approvals.json");
106
89
  try {
@@ -109,53 +92,77 @@ function readExecApprovalsConfig() {
109
92
  return null;
110
93
  }
111
94
  }
112
- function startExecApprovalsClient(apiKey, policyId, baseUrl) {
95
+ function startExecApprovalsServer(apiKey, policyId, baseUrl) {
113
96
  const cfg = readExecApprovalsConfig();
114
- if (!cfg?.socket?.path || !cfg?.socket?.token) return;
115
- const { path: sockPath, token } = cfg.socket;
116
- function connect() {
117
- const client = net.createConnection(sockPath);
97
+ if (!cfg?.socket?.path || !cfg?.socket?.token) {
98
+ console.warn("[fastgrc] exec-approvals: no socket config found \u2014 webchat execs will not be evaluated");
99
+ return;
100
+ }
101
+ const { path: sockPath, token: configToken } = cfg.socket;
102
+ try {
103
+ fs2.unlinkSync(sockPath);
104
+ } catch {
105
+ }
106
+ const server = net.createServer((conn) => {
118
107
  let buffer = "";
119
- client.on("connect", () => {
120
- console.log("[fastgrc] exec-approvals socket connected");
121
- });
122
- client.on("data", async (buf) => {
123
- buffer += buf.toString();
124
- let req;
108
+ conn.on("data", (chunk) => {
109
+ buffer += chunk.toString("utf8");
110
+ const idx = buffer.indexOf("\n");
111
+ if (idx === -1) return;
112
+ const line = buffer.slice(0, idx).trim();
113
+ buffer = "";
114
+ if (!line) {
115
+ conn.destroy();
116
+ return;
117
+ }
118
+ let msg;
125
119
  try {
126
- req = JSON.parse(buffer);
120
+ msg = JSON.parse(line);
127
121
  } catch {
122
+ conn.destroy();
128
123
  return;
129
124
  }
130
- buffer = "";
131
- if (!verifyHmac(req, token)) {
132
- console.warn("[fastgrc] exec-approvals: HMAC verification failed \u2014 ignoring request");
125
+ if (msg.type !== "request" || msg.token !== configToken) {
126
+ conn.destroy();
133
127
  return;
134
128
  }
135
- let decision = "allow-once";
136
- try {
137
- const result = await evaluate({
138
- toolName: "Exec",
139
- args: { command: req.command, rawCommand: req.rawCommand, cwd: req.cwd },
140
- agentId: req.agentId,
141
- apiKey,
142
- policyId,
143
- baseUrl
144
- });
129
+ const req = msg.request ?? {};
130
+ const command = String(req.command ?? req.commandPreview ?? "unknown");
131
+ const agentId = req.agentId || void 0;
132
+ evaluate({
133
+ toolName: "Exec",
134
+ args: { command, cwd: req.cwd },
135
+ agentId,
136
+ apiKey,
137
+ policyId,
138
+ baseUrl
139
+ }).then((result) => {
140
+ let decision = "allow-once";
145
141
  if (result && (result.decision === "block" || result.decision === "require_approval")) {
146
142
  decision = "deny";
147
- const msg = result.policyContext?.matchedRule ? `[fastgrc] exec blocked: [${result.policyContext.matchedRule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`;
148
- console.warn(msg);
143
+ const rule = result.policyContext?.matchedRule;
144
+ console.warn(rule ? `[fastgrc] exec blocked: [${rule}] ${result.reasoning}` : `[fastgrc] exec blocked: ${result.reasoning}`);
149
145
  }
150
- } catch {
151
- }
152
- const response = sign({ approvalId: req.approvalId, decision }, token);
153
- client.write(JSON.stringify(response));
146
+ conn.write(JSON.stringify({ type: "decision", decision }) + "\n");
147
+ conn.destroy();
148
+ }).catch(() => {
149
+ conn.write(JSON.stringify({ type: "decision", decision: "allow-once" }) + "\n");
150
+ conn.destroy();
151
+ });
154
152
  });
155
- client.on("error", () => setTimeout(connect, 5e3));
156
- client.on("close", () => setTimeout(connect, 5e3));
157
- }
158
- connect();
153
+ conn.on("error", () => {
154
+ });
155
+ });
156
+ server.listen(sockPath, () => {
157
+ try {
158
+ fs2.chmodSync(sockPath, 384);
159
+ } catch {
160
+ }
161
+ console.log(`[fastgrc] exec-approvals server listening on ${sockPath}`);
162
+ });
163
+ server.on("error", (err) => {
164
+ console.warn(`[fastgrc] exec-approvals server error: ${err.message}`);
165
+ });
159
166
  }
160
167
  var pluginEntry = {
161
168
  id: "fastgrc",
@@ -201,12 +208,12 @@ var pluginEntry = {
201
208
  }
202
209
  return void 0;
203
210
  });
204
- startExecApprovalsClient(apiKey, policyId, DEFAULT_BASE_URL2);
211
+ startExecApprovalsServer(apiKey, policyId, DEFAULT_BASE_URL2);
205
212
  }
206
213
  };
207
214
  var plugin_default = pluginEntry;
208
215
  export {
209
216
  plugin_default as default,
210
217
  readExecApprovalsConfig,
211
- startExecApprovalsClient
218
+ startExecApprovalsServer
212
219
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "fastgrc-openclaw",
3
- "version": "1.0.29",
3
+ "version": "1.0.30",
4
4
  "description": "FastGRC agent compliance plugin for OpenClaw — evaluates every tool call against your policy before it executes",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",