codebot-ai 2.0.2 → 2.1.1
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/banner.d.ts +38 -5
- package/dist/banner.js +262 -80
- package/dist/cli.js +17 -4
- package/dist/encryption.d.ts +67 -0
- package/dist/encryption.js +209 -0
- package/dist/index.d.ts +8 -2
- package/dist/index.js +29 -2
- package/dist/metrics.d.ts +35 -1
- package/dist/metrics.js +130 -2
- package/dist/policy.d.ts +26 -0
- package/dist/policy.js +85 -4
- package/package.json +14 -4
package/dist/policy.js
CHANGED
|
@@ -88,6 +88,12 @@ exports.DEFAULT_POLICY = {
|
|
|
88
88
|
max_files_per_operation: 20,
|
|
89
89
|
cost_limit_usd: 0, // 0 = no limit
|
|
90
90
|
},
|
|
91
|
+
rbac: {
|
|
92
|
+
enabled: false,
|
|
93
|
+
user_roles: {},
|
|
94
|
+
roles: {},
|
|
95
|
+
default_role: undefined,
|
|
96
|
+
},
|
|
91
97
|
};
|
|
92
98
|
// ── Policy Loader ──
|
|
93
99
|
/**
|
|
@@ -145,6 +151,8 @@ function validatePolicy(obj) {
|
|
|
145
151
|
return false;
|
|
146
152
|
if (p.limits !== undefined && typeof p.limits !== 'object')
|
|
147
153
|
return false;
|
|
154
|
+
if (p.rbac !== undefined && typeof p.rbac !== 'object')
|
|
155
|
+
return false;
|
|
148
156
|
return true;
|
|
149
157
|
}
|
|
150
158
|
/**
|
|
@@ -178,13 +186,60 @@ class PolicyEnforcer {
|
|
|
178
186
|
this.policy = policy || loadPolicy(projectRoot);
|
|
179
187
|
this.projectRoot = projectRoot || process.cwd();
|
|
180
188
|
}
|
|
189
|
+
/** Resolve the current user's role and return merged policy */
|
|
190
|
+
currentUser = null;
|
|
191
|
+
/** Set the current user for RBAC resolution */
|
|
192
|
+
setUser(username) {
|
|
193
|
+
this.currentUser = username;
|
|
194
|
+
}
|
|
195
|
+
/** Get the current OS username */
|
|
196
|
+
getCurrentUser() {
|
|
197
|
+
return this.currentUser || os.userInfo().username || 'unknown';
|
|
198
|
+
}
|
|
199
|
+
/** Resolve the role for the current user */
|
|
200
|
+
resolveRole() {
|
|
201
|
+
const rbac = this.policy.rbac;
|
|
202
|
+
if (!rbac?.enabled)
|
|
203
|
+
return null;
|
|
204
|
+
const user = this.getCurrentUser();
|
|
205
|
+
const roleName = rbac.user_roles?.[user] || rbac.default_role || null;
|
|
206
|
+
return roleName;
|
|
207
|
+
}
|
|
208
|
+
/** Get the effective policy for the current user (base policy merged with role overrides) */
|
|
209
|
+
getEffectivePolicy() {
|
|
210
|
+
const rbac = this.policy.rbac;
|
|
211
|
+
if (!rbac?.enabled)
|
|
212
|
+
return this.policy;
|
|
213
|
+
const roleName = this.resolveRole();
|
|
214
|
+
if (!roleName || !rbac.roles?.[roleName])
|
|
215
|
+
return this.policy;
|
|
216
|
+
const role = rbac.roles[roleName];
|
|
217
|
+
// Merge role overrides on top of base policy
|
|
218
|
+
const effective = { ...this.policy };
|
|
219
|
+
if (role.tools) {
|
|
220
|
+
effective.tools = {
|
|
221
|
+
...effective.tools,
|
|
222
|
+
...role.tools,
|
|
223
|
+
permissions: { ...effective.tools?.permissions, ...role.tools.permissions },
|
|
224
|
+
capabilities: { ...effective.tools?.capabilities, ...role.tools.capabilities },
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
if (role.filesystem) {
|
|
228
|
+
effective.filesystem = { ...effective.filesystem, ...role.filesystem };
|
|
229
|
+
}
|
|
230
|
+
if (role.limits) {
|
|
231
|
+
effective.limits = { ...effective.limits, ...role.limits };
|
|
232
|
+
}
|
|
233
|
+
return effective;
|
|
234
|
+
}
|
|
181
235
|
getPolicy() {
|
|
182
236
|
return this.policy;
|
|
183
237
|
}
|
|
184
238
|
// ── Tool Access ──
|
|
185
239
|
/** Check if a tool is enabled by policy. Returns { allowed, reason }. */
|
|
186
240
|
isToolAllowed(toolName) {
|
|
187
|
-
const
|
|
241
|
+
const effective = this.getEffectivePolicy();
|
|
242
|
+
const tools = effective.tools;
|
|
188
243
|
if (!tools)
|
|
189
244
|
return { allowed: true };
|
|
190
245
|
// If explicit disabled list contains it, block
|
|
@@ -203,7 +258,7 @@ class PolicyEnforcer {
|
|
|
203
258
|
}
|
|
204
259
|
/** Get the permission level for a tool (policy override or null for default). */
|
|
205
260
|
getToolPermission(toolName) {
|
|
206
|
-
return this.
|
|
261
|
+
return this.getEffectivePolicy().tools?.permissions?.[toolName] || null;
|
|
207
262
|
}
|
|
208
263
|
// ── Filesystem Access ──
|
|
209
264
|
/** Check if a path is writable according to policy. */
|
|
@@ -331,11 +386,11 @@ class PolicyEnforcer {
|
|
|
331
386
|
// ── Capabilities (v1.8.0) ──
|
|
332
387
|
/** Get capability restrictions for a tool. undefined = unrestricted. */
|
|
333
388
|
getToolCapabilities(toolName) {
|
|
334
|
-
return this.
|
|
389
|
+
return this.getEffectivePolicy().tools?.capabilities?.[toolName];
|
|
335
390
|
}
|
|
336
391
|
/** Check a specific capability for a tool. Returns { allowed, reason }. */
|
|
337
392
|
checkCapability(toolName, capabilityType, value) {
|
|
338
|
-
const caps = this.
|
|
393
|
+
const caps = this.getEffectivePolicy().tools?.capabilities;
|
|
339
394
|
if (!caps)
|
|
340
395
|
return { allowed: true };
|
|
341
396
|
const checker = new capabilities_1.CapabilityChecker(caps, this.projectRoot);
|
|
@@ -439,6 +494,32 @@ function generateDefaultPolicyFile() {
|
|
|
439
494
|
max_files_per_operation: 20,
|
|
440
495
|
cost_limit_usd: 0,
|
|
441
496
|
},
|
|
497
|
+
rbac: {
|
|
498
|
+
enabled: false,
|
|
499
|
+
default_role: 'developer',
|
|
500
|
+
user_roles: {},
|
|
501
|
+
roles: {
|
|
502
|
+
admin: {
|
|
503
|
+
tools: { disabled: [] },
|
|
504
|
+
limits: { max_iterations: 100, cost_limit_usd: 50.0 },
|
|
505
|
+
},
|
|
506
|
+
developer: {
|
|
507
|
+
tools: {
|
|
508
|
+
disabled: ['ssh_remote'],
|
|
509
|
+
permissions: { execute: 'prompt', write_file: 'prompt' },
|
|
510
|
+
},
|
|
511
|
+
limits: { max_iterations: 50, cost_limit_usd: 10.0 },
|
|
512
|
+
},
|
|
513
|
+
reviewer: {
|
|
514
|
+
tools: {
|
|
515
|
+
disabled: ['execute', 'write_file', 'edit_file', 'batch_edit', 'ssh_remote', 'docker', 'database'],
|
|
516
|
+
permissions: {},
|
|
517
|
+
},
|
|
518
|
+
filesystem: { writable_paths: [] },
|
|
519
|
+
limits: { max_iterations: 10, cost_limit_usd: 2.0 },
|
|
520
|
+
},
|
|
521
|
+
},
|
|
522
|
+
},
|
|
442
523
|
}, null, 2) + '\n';
|
|
443
524
|
}
|
|
444
525
|
//# sourceMappingURL=policy.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codebot-ai",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Zero-dependency autonomous AI agent. Code, browse, search, automate. Works with any LLM — Ollama, Claude, GPT, Gemini, DeepSeek, Groq, Mistral, Grok.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -12,7 +12,12 @@
|
|
|
12
12
|
"dev": "tsc --watch",
|
|
13
13
|
"start": "node dist/cli.js",
|
|
14
14
|
"test": "node --test dist/*.test.js dist/**/*.test.js",
|
|
15
|
-
"lint": "tsc --noEmit",
|
|
15
|
+
"lint": "eslint src/ && tsc --noEmit",
|
|
16
|
+
"lint:fix": "eslint src/ --fix",
|
|
17
|
+
"format": "prettier --write 'src/**/*.ts' '*.json' '*.md'",
|
|
18
|
+
"format:check": "prettier --check 'src/**/*.ts' '*.json' '*.md'",
|
|
19
|
+
"typecheck": "tsc --noEmit",
|
|
20
|
+
"clean": "rm -rf dist",
|
|
16
21
|
"prepublishOnly": "npm run build"
|
|
17
22
|
},
|
|
18
23
|
"keywords": [
|
|
@@ -71,7 +76,12 @@
|
|
|
71
76
|
"LICENSE"
|
|
72
77
|
],
|
|
73
78
|
"devDependencies": {
|
|
74
|
-
"
|
|
75
|
-
"@
|
|
79
|
+
"@types/node": "^20.0.0",
|
|
80
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
81
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
82
|
+
"eslint": "^10.0.2",
|
|
83
|
+
"eslint-config-prettier": "^10.1.8",
|
|
84
|
+
"prettier": "^3.8.1",
|
|
85
|
+
"typescript": "^5.5.0"
|
|
76
86
|
}
|
|
77
87
|
}
|