sovr-mcp-proxy 6.0.1 → 7.0.0
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/LICENSE +54 -19
- package/README.md +387 -164
- package/dist/cli.js +1553 -24
- package/dist/cli.mjs +185 -18
- package/dist/commandNormalizer.d.mts +95 -0
- package/dist/commandNormalizer.d.ts +95 -0
- package/dist/commandNormalizer.js +365 -0
- package/dist/commandNormalizer.mjs +336 -0
- package/dist/hooksAdapter.d.mts +122 -0
- package/dist/hooksAdapter.d.ts +122 -0
- package/dist/hooksAdapter.js +321 -0
- package/dist/hooksAdapter.mjs +291 -0
- package/dist/index.js +1065 -2
- package/dist/index.mjs +98 -2
- package/dist/toolReplacement.d.mts +108 -0
- package/dist/toolReplacement.d.ts +108 -0
- package/dist/toolReplacement.js +234 -0
- package/dist/toolReplacement.mjs +204 -0
- package/dist/whitelistEngine.d.mts +167 -0
- package/dist/whitelistEngine.d.ts +167 -0
- package/dist/whitelistEngine.js +435 -0
- package/dist/whitelistEngine.mjs +403 -0
- package/package.json +46 -41
- package/server.json +0 -14
|
@@ -0,0 +1,435 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/whitelistEngine.ts
|
|
21
|
+
var whitelistEngine_exports = {};
|
|
22
|
+
__export(whitelistEngine_exports, {
|
|
23
|
+
PRESETS: () => PRESETS,
|
|
24
|
+
PRESET_DEVELOPER: () => PRESET_DEVELOPER,
|
|
25
|
+
PRESET_PRODUCTION: () => PRESET_PRODUCTION,
|
|
26
|
+
PRESET_READONLY: () => PRESET_READONLY,
|
|
27
|
+
WhitelistEngine: () => WhitelistEngine,
|
|
28
|
+
autoLoadPolicy: () => autoLoadPolicy,
|
|
29
|
+
generatePolicyFile: () => generatePolicyFile,
|
|
30
|
+
loadPolicy: () => loadPolicy
|
|
31
|
+
});
|
|
32
|
+
module.exports = __toCommonJS(whitelistEngine_exports);
|
|
33
|
+
var import_node_fs = require("fs");
|
|
34
|
+
var import_node_path = require("path");
|
|
35
|
+
var PRESET_READONLY = {
|
|
36
|
+
version: "1.0",
|
|
37
|
+
mode: "whitelist",
|
|
38
|
+
rules: [
|
|
39
|
+
{ pattern: "ls *", allow: true, description: "List directory" },
|
|
40
|
+
{ pattern: "cat *", allow: true, description: "Read file" },
|
|
41
|
+
{ pattern: "head *", allow: true, description: "Read file head" },
|
|
42
|
+
{ pattern: "tail *", allow: true, description: "Read file tail" },
|
|
43
|
+
{ pattern: "find *", allow: true, description: "Find files", max_args: 10 },
|
|
44
|
+
{ pattern: "grep *", allow: true, description: "Search in files" },
|
|
45
|
+
{ pattern: "wc *", allow: true, description: "Word count" },
|
|
46
|
+
{ pattern: "file *", allow: true, description: "File type" },
|
|
47
|
+
{ pattern: "pwd", allow: true, description: "Print working directory" },
|
|
48
|
+
{ pattern: "whoami", allow: true, description: "Current user" },
|
|
49
|
+
{ pattern: "date", allow: true, description: "Current date" },
|
|
50
|
+
{ pattern: "echo *", allow: true, description: "Echo text" }
|
|
51
|
+
],
|
|
52
|
+
settings: {
|
|
53
|
+
max_command_length: 500,
|
|
54
|
+
allow_env_expansion: false,
|
|
55
|
+
allow_subshell: false,
|
|
56
|
+
allow_pipes: true,
|
|
57
|
+
allow_chains: false,
|
|
58
|
+
allow_redirects: false
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
var PRESET_DEVELOPER = {
|
|
62
|
+
version: "1.0",
|
|
63
|
+
mode: "whitelist",
|
|
64
|
+
rules: [
|
|
65
|
+
// Read operations
|
|
66
|
+
...PRESET_READONLY.rules,
|
|
67
|
+
// Git (safe operations)
|
|
68
|
+
{ pattern: "git status", allow: true, description: "Git status" },
|
|
69
|
+
{ pattern: "git diff *", allow: true, description: "Git diff" },
|
|
70
|
+
{ pattern: "git log *", allow: true, description: "Git log" },
|
|
71
|
+
{ pattern: "git branch *", allow: true, description: "Git branch" },
|
|
72
|
+
{ pattern: "git add *", allow: true, description: "Git add" },
|
|
73
|
+
{ pattern: "git commit *", allow: true, description: "Git commit" },
|
|
74
|
+
{ pattern: "git push *", allow: true, require_approval: true, description: "Git push (requires approval)" },
|
|
75
|
+
{ pattern: "git pull *", allow: true, description: "Git pull" },
|
|
76
|
+
{ pattern: "git checkout *", allow: true, description: "Git checkout" },
|
|
77
|
+
{ pattern: "git stash *", allow: true, description: "Git stash" },
|
|
78
|
+
// Node.js / npm
|
|
79
|
+
{ pattern: "node *", allow: true, description: "Run Node.js" },
|
|
80
|
+
{ pattern: "npm run *", allow: true, description: "Run npm script" },
|
|
81
|
+
{ pattern: "npm test", allow: true, description: "Run tests" },
|
|
82
|
+
{ pattern: "npm install *", allow: true, description: "Install packages" },
|
|
83
|
+
{ pattern: "npx *", allow: true, description: "Run npx" },
|
|
84
|
+
{ pattern: "pnpm *", allow: true, description: "Run pnpm" },
|
|
85
|
+
{ pattern: "yarn *", allow: true, description: "Run yarn" },
|
|
86
|
+
// Python
|
|
87
|
+
{ pattern: "python3 *", allow: true, description: "Run Python", max_args: 20 },
|
|
88
|
+
{ pattern: "pip install *", allow: true, description: "Install Python packages" },
|
|
89
|
+
{ pattern: "pip3 install *", allow: true, description: "Install Python packages" },
|
|
90
|
+
// Build tools
|
|
91
|
+
{ pattern: "make *", allow: true, description: "Run make" },
|
|
92
|
+
{ pattern: "cargo *", allow: true, description: "Run cargo" },
|
|
93
|
+
// File operations (limited)
|
|
94
|
+
{ pattern: "mkdir *", allow: true, description: "Create directory" },
|
|
95
|
+
{ pattern: "cp *", allow: true, description: "Copy files" },
|
|
96
|
+
{ pattern: "mv *", allow: true, description: "Move files" },
|
|
97
|
+
{ pattern: "touch *", allow: true, description: "Create empty file" },
|
|
98
|
+
// Dangerous operations — require approval
|
|
99
|
+
{ pattern: "rm *", allow: true, require_approval: true, description: "Delete files (requires approval)" },
|
|
100
|
+
{ pattern: "npm publish *", allow: true, require_approval: true, description: "Publish package (requires approval)" },
|
|
101
|
+
{ pattern: "docker *", allow: true, require_approval: true, description: "Docker operations (requires approval)" }
|
|
102
|
+
],
|
|
103
|
+
settings: {
|
|
104
|
+
max_command_length: 2e3,
|
|
105
|
+
allow_env_expansion: true,
|
|
106
|
+
allow_subshell: false,
|
|
107
|
+
allow_pipes: true,
|
|
108
|
+
allow_chains: true,
|
|
109
|
+
allow_redirects: true
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
var PRESET_PRODUCTION = {
|
|
113
|
+
version: "1.0",
|
|
114
|
+
mode: "whitelist",
|
|
115
|
+
rules: [
|
|
116
|
+
{ pattern: "echo *", allow: true, description: "Echo" },
|
|
117
|
+
{ pattern: "date", allow: true, description: "Date" },
|
|
118
|
+
{ pattern: "uptime", allow: true, description: "Uptime" },
|
|
119
|
+
{ pattern: "df *", allow: true, description: "Disk usage" },
|
|
120
|
+
{ pattern: "free *", allow: true, description: "Memory usage" },
|
|
121
|
+
{ pattern: "ps *", allow: true, description: "Process list" },
|
|
122
|
+
{ pattern: "curl *", allow: true, require_approval: true, description: "HTTP request (requires approval)" }
|
|
123
|
+
],
|
|
124
|
+
default_action: "deny",
|
|
125
|
+
settings: {
|
|
126
|
+
max_command_length: 500,
|
|
127
|
+
allow_env_expansion: false,
|
|
128
|
+
allow_subshell: false,
|
|
129
|
+
allow_pipes: false,
|
|
130
|
+
allow_chains: false,
|
|
131
|
+
allow_redirects: false
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
var PRESETS = {
|
|
135
|
+
readonly: PRESET_READONLY,
|
|
136
|
+
developer: PRESET_DEVELOPER,
|
|
137
|
+
production: PRESET_PRODUCTION
|
|
138
|
+
};
|
|
139
|
+
var WhitelistEngine = class {
|
|
140
|
+
policy;
|
|
141
|
+
constructor(policy) {
|
|
142
|
+
this.policy = policy;
|
|
143
|
+
this.policy.rules.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Evaluate a command against the whitelist policy.
|
|
147
|
+
*/
|
|
148
|
+
evaluate(command) {
|
|
149
|
+
const violations = [];
|
|
150
|
+
const structuralCheck = this.checkStructural(command);
|
|
151
|
+
violations.push(...structuralCheck.violations);
|
|
152
|
+
if (structuralCheck.blocked) {
|
|
153
|
+
return {
|
|
154
|
+
allowed: false,
|
|
155
|
+
require_approval: false,
|
|
156
|
+
reason: `Structural violation: ${violations.join(", ")}`,
|
|
157
|
+
risk: "critical",
|
|
158
|
+
violations
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
const enabledRules = this.policy.rules.filter((r) => r.enabled !== false);
|
|
162
|
+
for (const rule of enabledRules) {
|
|
163
|
+
if (matchPattern(command, rule.pattern)) {
|
|
164
|
+
if (rule.max_args !== void 0) {
|
|
165
|
+
const argCount = command.split(/\s+/).length - 1;
|
|
166
|
+
if (argCount > rule.max_args) {
|
|
167
|
+
violations.push(`Too many arguments: ${argCount} > ${rule.max_args}`);
|
|
168
|
+
return {
|
|
169
|
+
allowed: false,
|
|
170
|
+
require_approval: false,
|
|
171
|
+
matched_rule: rule,
|
|
172
|
+
reason: `Argument limit exceeded for pattern "${rule.pattern}"`,
|
|
173
|
+
risk: "high",
|
|
174
|
+
violations
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
if (rule.allow) {
|
|
179
|
+
return {
|
|
180
|
+
allowed: true,
|
|
181
|
+
require_approval: rule.require_approval ?? false,
|
|
182
|
+
matched_rule: rule,
|
|
183
|
+
reason: rule.description || `Matched whitelist pattern: ${rule.pattern}`,
|
|
184
|
+
risk: rule.require_approval ? "medium" : "low",
|
|
185
|
+
violations
|
|
186
|
+
};
|
|
187
|
+
} else {
|
|
188
|
+
return {
|
|
189
|
+
allowed: false,
|
|
190
|
+
require_approval: false,
|
|
191
|
+
matched_rule: rule,
|
|
192
|
+
reason: rule.description || `Matched blacklist pattern: ${rule.pattern}`,
|
|
193
|
+
risk: "high",
|
|
194
|
+
violations
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
switch (this.policy.mode) {
|
|
200
|
+
case "whitelist":
|
|
201
|
+
return {
|
|
202
|
+
allowed: false,
|
|
203
|
+
require_approval: false,
|
|
204
|
+
reason: `No whitelist rule matches command. In whitelist mode, unlisted commands are DENIED.`,
|
|
205
|
+
risk: "high",
|
|
206
|
+
violations
|
|
207
|
+
};
|
|
208
|
+
case "blacklist":
|
|
209
|
+
return {
|
|
210
|
+
allowed: true,
|
|
211
|
+
require_approval: false,
|
|
212
|
+
reason: "No blacklist rule matches. Command allowed by default.",
|
|
213
|
+
risk: "medium",
|
|
214
|
+
violations
|
|
215
|
+
};
|
|
216
|
+
case "hybrid": {
|
|
217
|
+
const defaultAction = this.policy.default_action || "deny";
|
|
218
|
+
return {
|
|
219
|
+
allowed: defaultAction === "allow",
|
|
220
|
+
require_approval: defaultAction === "escalate",
|
|
221
|
+
reason: `No rule matches. Hybrid mode default: ${defaultAction}`,
|
|
222
|
+
risk: defaultAction === "allow" ? "medium" : "high",
|
|
223
|
+
violations
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Check structural constraints (pipes, chains, subshells, etc.)
|
|
230
|
+
*/
|
|
231
|
+
checkStructural(command) {
|
|
232
|
+
const violations = [];
|
|
233
|
+
const settings = this.policy.settings || {};
|
|
234
|
+
if (settings.max_command_length && command.length > settings.max_command_length) {
|
|
235
|
+
violations.push(`Command too long: ${command.length} > ${settings.max_command_length}`);
|
|
236
|
+
}
|
|
237
|
+
if (settings.allow_subshell === false) {
|
|
238
|
+
if (/\$\(/.test(command) || /`[^`]+`/.test(command)) {
|
|
239
|
+
violations.push("Subshell execution not allowed");
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
if (settings.allow_pipes === false) {
|
|
243
|
+
if (/\|(?!\|)/.test(command)) {
|
|
244
|
+
violations.push("Pipe chains not allowed");
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
if (settings.allow_chains === false) {
|
|
248
|
+
if (/[;&]|&&|\|\|/.test(command)) {
|
|
249
|
+
violations.push("Command chaining not allowed");
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
if (settings.allow_redirects === false) {
|
|
253
|
+
if (/[<>]|>>/.test(command)) {
|
|
254
|
+
violations.push("Output redirection not allowed");
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
if (settings.allow_env_expansion === false) {
|
|
258
|
+
if (/\$[A-Za-z_]/.test(command) || /\$\{/.test(command)) {
|
|
259
|
+
violations.push("Environment variable expansion not allowed");
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return {
|
|
263
|
+
blocked: violations.length > 0,
|
|
264
|
+
violations
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Get the current policy.
|
|
269
|
+
*/
|
|
270
|
+
getPolicy() {
|
|
271
|
+
return { ...this.policy };
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Add a rule dynamically.
|
|
275
|
+
*/
|
|
276
|
+
addRule(rule) {
|
|
277
|
+
this.policy.rules.push(rule);
|
|
278
|
+
this.policy.rules.sort((a, b) => (b.priority ?? 0) - (a.priority ?? 0));
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Remove a rule by pattern.
|
|
282
|
+
*/
|
|
283
|
+
removeRule(pattern) {
|
|
284
|
+
const idx = this.policy.rules.findIndex((r) => r.pattern === pattern);
|
|
285
|
+
if (idx >= 0) {
|
|
286
|
+
this.policy.rules.splice(idx, 1);
|
|
287
|
+
return true;
|
|
288
|
+
}
|
|
289
|
+
return false;
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* List all rules.
|
|
293
|
+
*/
|
|
294
|
+
listRules() {
|
|
295
|
+
return [...this.policy.rules];
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
function matchPattern(command, pattern) {
|
|
299
|
+
const normalizedCmd = command.trim().replace(/\s+/g, " ");
|
|
300
|
+
const normalizedPattern = pattern.trim().replace(/\s+/g, " ");
|
|
301
|
+
const regexStr = "^" + normalizedPattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".") + "$";
|
|
302
|
+
try {
|
|
303
|
+
return new RegExp(regexStr).test(normalizedCmd);
|
|
304
|
+
} catch {
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function loadPolicy(filePath) {
|
|
309
|
+
if (!(0, import_node_fs.existsSync)(filePath)) {
|
|
310
|
+
throw new Error(`Policy file not found: ${filePath}`);
|
|
311
|
+
}
|
|
312
|
+
const raw = (0, import_node_fs.readFileSync)(filePath, "utf-8");
|
|
313
|
+
try {
|
|
314
|
+
return JSON.parse(raw);
|
|
315
|
+
} catch {
|
|
316
|
+
}
|
|
317
|
+
return parseSimpleYaml(raw);
|
|
318
|
+
}
|
|
319
|
+
function autoLoadPolicy(projectDir) {
|
|
320
|
+
const candidates = [
|
|
321
|
+
(0, import_node_path.join)(projectDir, ".sovr", "policy.json"),
|
|
322
|
+
(0, import_node_path.join)(projectDir, ".sovr", "policy.yaml"),
|
|
323
|
+
(0, import_node_path.join)(projectDir, ".sovr", "policy.yml"),
|
|
324
|
+
(0, import_node_path.join)(projectDir, "sovr.policy.json")
|
|
325
|
+
];
|
|
326
|
+
for (const candidate of candidates) {
|
|
327
|
+
if ((0, import_node_fs.existsSync)(candidate)) {
|
|
328
|
+
return loadPolicy(candidate);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
return null;
|
|
332
|
+
}
|
|
333
|
+
function parseSimpleYaml(raw) {
|
|
334
|
+
const lines = raw.split("\n");
|
|
335
|
+
const policy = {
|
|
336
|
+
version: "1.0",
|
|
337
|
+
mode: "whitelist",
|
|
338
|
+
rules: []
|
|
339
|
+
};
|
|
340
|
+
let currentRule = null;
|
|
341
|
+
let inRules = false;
|
|
342
|
+
for (const line of lines) {
|
|
343
|
+
const trimmed = line.trim();
|
|
344
|
+
if (!trimmed || trimmed.startsWith("#")) continue;
|
|
345
|
+
if (trimmed.startsWith("version:")) {
|
|
346
|
+
policy.version = trimmed.split(":").slice(1).join(":").trim().replace(/['"]/g, "");
|
|
347
|
+
} else if (trimmed.startsWith("mode:")) {
|
|
348
|
+
policy.mode = trimmed.split(":").slice(1).join(":").trim().replace(/['"]/g, "");
|
|
349
|
+
} else if (trimmed === "rules:") {
|
|
350
|
+
inRules = true;
|
|
351
|
+
} else if (inRules && trimmed.startsWith("- pattern:")) {
|
|
352
|
+
if (currentRule?.pattern) {
|
|
353
|
+
policy.rules.push(currentRule);
|
|
354
|
+
}
|
|
355
|
+
currentRule = {
|
|
356
|
+
pattern: trimmed.replace("- pattern:", "").trim().replace(/['"]/g, ""),
|
|
357
|
+
allow: true,
|
|
358
|
+
enabled: true
|
|
359
|
+
};
|
|
360
|
+
} else if (inRules && currentRule) {
|
|
361
|
+
if (trimmed.startsWith("allow:")) {
|
|
362
|
+
currentRule.allow = trimmed.includes("true");
|
|
363
|
+
} else if (trimmed.startsWith("description:")) {
|
|
364
|
+
currentRule.description = trimmed.split(":").slice(1).join(":").trim().replace(/['"]/g, "");
|
|
365
|
+
} else if (trimmed.startsWith("require_approval:")) {
|
|
366
|
+
currentRule.require_approval = trimmed.includes("true");
|
|
367
|
+
} else if (trimmed.startsWith("max_args:")) {
|
|
368
|
+
currentRule.max_args = parseInt(trimmed.split(":")[1].trim());
|
|
369
|
+
} else if (trimmed.startsWith("priority:")) {
|
|
370
|
+
currentRule.priority = parseInt(trimmed.split(":")[1].trim());
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
if (currentRule?.pattern) {
|
|
375
|
+
policy.rules.push(currentRule);
|
|
376
|
+
}
|
|
377
|
+
return policy;
|
|
378
|
+
}
|
|
379
|
+
function generatePolicyFile(preset, format = "yaml") {
|
|
380
|
+
const policy = PRESETS[preset];
|
|
381
|
+
if (!policy) {
|
|
382
|
+
throw new Error(`Unknown preset: ${preset}. Available: ${Object.keys(PRESETS).join(", ")}`);
|
|
383
|
+
}
|
|
384
|
+
if (format === "json") {
|
|
385
|
+
return JSON.stringify(policy, null, 2);
|
|
386
|
+
}
|
|
387
|
+
let yaml = `# SOVR Whitelist Policy
|
|
388
|
+
`;
|
|
389
|
+
yaml += `# Preset: ${preset}
|
|
390
|
+
`;
|
|
391
|
+
yaml += `# Generated: ${(/* @__PURE__ */ new Date()).toISOString()}
|
|
392
|
+
|
|
393
|
+
`;
|
|
394
|
+
yaml += `version: "${policy.version}"
|
|
395
|
+
`;
|
|
396
|
+
yaml += `mode: ${policy.mode}
|
|
397
|
+
|
|
398
|
+
`;
|
|
399
|
+
yaml += `rules:
|
|
400
|
+
`;
|
|
401
|
+
for (const rule of policy.rules) {
|
|
402
|
+
yaml += ` - pattern: "${rule.pattern}"
|
|
403
|
+
`;
|
|
404
|
+
yaml += ` allow: ${rule.allow}
|
|
405
|
+
`;
|
|
406
|
+
if (rule.description) yaml += ` description: "${rule.description}"
|
|
407
|
+
`;
|
|
408
|
+
if (rule.require_approval) yaml += ` require_approval: true
|
|
409
|
+
`;
|
|
410
|
+
if (rule.max_args !== void 0) yaml += ` max_args: ${rule.max_args}
|
|
411
|
+
`;
|
|
412
|
+
yaml += `
|
|
413
|
+
`;
|
|
414
|
+
}
|
|
415
|
+
if (policy.settings) {
|
|
416
|
+
yaml += `settings:
|
|
417
|
+
`;
|
|
418
|
+
for (const [key, value] of Object.entries(policy.settings)) {
|
|
419
|
+
yaml += ` ${key}: ${value}
|
|
420
|
+
`;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return yaml;
|
|
424
|
+
}
|
|
425
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
426
|
+
0 && (module.exports = {
|
|
427
|
+
PRESETS,
|
|
428
|
+
PRESET_DEVELOPER,
|
|
429
|
+
PRESET_PRODUCTION,
|
|
430
|
+
PRESET_READONLY,
|
|
431
|
+
WhitelistEngine,
|
|
432
|
+
autoLoadPolicy,
|
|
433
|
+
generatePolicyFile,
|
|
434
|
+
loadPolicy
|
|
435
|
+
});
|