agentshield-sdk 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/CHANGELOG.md +191 -0
- package/LICENSE +21 -0
- package/README.md +975 -0
- package/bin/agent-shield.js +680 -0
- package/package.json +118 -0
- package/src/adaptive.js +330 -0
- package/src/agent-protocol.js +998 -0
- package/src/alert-tuning.js +480 -0
- package/src/allowlist.js +603 -0
- package/src/audit-immutable.js +914 -0
- package/src/audit-streaming.js +469 -0
- package/src/badges.js +196 -0
- package/src/behavior-profiling.js +289 -0
- package/src/benchmark-harness.js +804 -0
- package/src/canary.js +271 -0
- package/src/certification.js +563 -0
- package/src/circuit-breaker.js +321 -0
- package/src/compliance.js +617 -0
- package/src/confidence-tuning.js +324 -0
- package/src/confused-deputy.js +624 -0
- package/src/context-scoring.js +360 -0
- package/src/conversation.js +494 -0
- package/src/cost-optimizer.js +1024 -0
- package/src/ctf.js +462 -0
- package/src/detector-core.js +1999 -0
- package/src/distributed.js +359 -0
- package/src/document-scanner.js +795 -0
- package/src/embedding.js +307 -0
- package/src/encoding.js +429 -0
- package/src/enterprise.js +405 -0
- package/src/errors.js +100 -0
- package/src/eu-ai-act.js +523 -0
- package/src/fuzzer.js +764 -0
- package/src/honeypot.js +328 -0
- package/src/i18n-patterns.js +523 -0
- package/src/index.js +430 -0
- package/src/integrations.js +528 -0
- package/src/llm-redteam.js +670 -0
- package/src/main.js +741 -0
- package/src/main.mjs +38 -0
- package/src/mcp-bridge.js +542 -0
- package/src/mcp-certification.js +846 -0
- package/src/mcp-sdk-integration.js +355 -0
- package/src/mcp-security-runtime.js +741 -0
- package/src/mcp-server.js +740 -0
- package/src/middleware.js +208 -0
- package/src/model-finetuning.js +884 -0
- package/src/model-fingerprint.js +1042 -0
- package/src/multi-agent-trust.js +453 -0
- package/src/multi-agent.js +404 -0
- package/src/multimodal.js +296 -0
- package/src/nist-mapping.js +505 -0
- package/src/observability.js +330 -0
- package/src/openclaw.js +450 -0
- package/src/otel.js +544 -0
- package/src/owasp-2025.js +483 -0
- package/src/pii.js +390 -0
- package/src/plugin-marketplace.js +628 -0
- package/src/plugin-system.js +349 -0
- package/src/policy-dsl.js +775 -0
- package/src/policy-extended.js +635 -0
- package/src/policy.js +443 -0
- package/src/presets.js +409 -0
- package/src/production.js +557 -0
- package/src/prompt-leakage.js +321 -0
- package/src/rag-vulnerability.js +579 -0
- package/src/redteam.js +475 -0
- package/src/response-handler.js +429 -0
- package/src/scanners.js +357 -0
- package/src/self-healing.js +363 -0
- package/src/semantic.js +339 -0
- package/src/shield-score.js +250 -0
- package/src/sso-saml.js +897 -0
- package/src/stream-scanner.js +806 -0
- package/src/testing.js +505 -0
- package/src/threat-encyclopedia.js +629 -0
- package/src/threat-intel-network.js +1017 -0
- package/src/token-analysis.js +467 -0
- package/src/tool-guard.js +412 -0
- package/src/tool-output-validator.js +354 -0
- package/src/utils.js +83 -0
- package/src/watermark.js +235 -0
- package/src/worker-scanner.js +601 -0
- package/types/index.d.ts +2088 -0
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Agent Shield — Enterprise Features
|
|
5
|
+
*
|
|
6
|
+
* - Multi-tenant support
|
|
7
|
+
* - Role-based policies
|
|
8
|
+
* - Debug mode with detailed traces
|
|
9
|
+
* - Policy inheritance and overrides
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { AgentShield } = require('./index');
|
|
13
|
+
const { loadPolicy } = require('./policy');
|
|
14
|
+
|
|
15
|
+
// =========================================================================
|
|
16
|
+
// Multi-Tenant Shield
|
|
17
|
+
// =========================================================================
|
|
18
|
+
|
|
19
|
+
class MultiTenantShield {
|
|
20
|
+
constructor(options = {}) {
|
|
21
|
+
this.tenants = new Map();
|
|
22
|
+
this.defaultPolicy = options.defaultPolicy || { sensitivity: 'high', blockOnThreat: true };
|
|
23
|
+
this.globalOverrides = options.globalOverrides || {};
|
|
24
|
+
this.onTenantCreated = options.onTenantCreated || null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Register a tenant with its own policy.
|
|
29
|
+
*/
|
|
30
|
+
registerTenant(tenantId, policy = {}) {
|
|
31
|
+
const mergedPolicy = { ...this.defaultPolicy, ...policy, ...this.globalOverrides };
|
|
32
|
+
const shield = new AgentShield(mergedPolicy);
|
|
33
|
+
|
|
34
|
+
this.tenants.set(tenantId, {
|
|
35
|
+
id: tenantId,
|
|
36
|
+
policy: mergedPolicy,
|
|
37
|
+
shield,
|
|
38
|
+
stats: { scans: 0, threats: 0, blocked: 0 },
|
|
39
|
+
createdAt: new Date().toISOString()
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
if (this.onTenantCreated) {
|
|
43
|
+
this.onTenantCreated(tenantId, mergedPolicy);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return this;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get or auto-create a tenant shield.
|
|
51
|
+
*/
|
|
52
|
+
getTenant(tenantId) {
|
|
53
|
+
if (!this.tenants.has(tenantId)) {
|
|
54
|
+
this.registerTenant(tenantId);
|
|
55
|
+
}
|
|
56
|
+
return this.tenants.get(tenantId);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Scan input for a specific tenant.
|
|
61
|
+
*/
|
|
62
|
+
scan(tenantId, text, options = {}) {
|
|
63
|
+
const tenant = this.getTenant(tenantId);
|
|
64
|
+
tenant.stats.scans++;
|
|
65
|
+
|
|
66
|
+
const result = tenant.shield.scan(text, options);
|
|
67
|
+
|
|
68
|
+
if (result.threats.length > 0) {
|
|
69
|
+
tenant.stats.threats += result.threats.length;
|
|
70
|
+
}
|
|
71
|
+
if (result.blocked) {
|
|
72
|
+
tenant.stats.blocked++;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return { ...result, tenantId };
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Scan input for a specific tenant.
|
|
80
|
+
*/
|
|
81
|
+
scanInput(tenantId, text) {
|
|
82
|
+
return this.scan(tenantId, text);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Scan output for a specific tenant.
|
|
87
|
+
*/
|
|
88
|
+
scanOutput(tenantId, text) {
|
|
89
|
+
const tenant = this.getTenant(tenantId);
|
|
90
|
+
return tenant.shield.scanOutput(text);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Update a tenant's policy.
|
|
95
|
+
*/
|
|
96
|
+
updatePolicy(tenantId, policy) {
|
|
97
|
+
const tenant = this.getTenant(tenantId);
|
|
98
|
+
tenant.policy = { ...tenant.policy, ...policy, ...this.globalOverrides };
|
|
99
|
+
tenant.shield = new AgentShield(tenant.policy);
|
|
100
|
+
return tenant.policy;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Get stats for all tenants.
|
|
105
|
+
*/
|
|
106
|
+
getAllStats() {
|
|
107
|
+
const stats = {};
|
|
108
|
+
for (const [id, tenant] of this.tenants) {
|
|
109
|
+
stats[id] = { ...tenant.stats, policy: tenant.policy };
|
|
110
|
+
}
|
|
111
|
+
return stats;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Remove a tenant.
|
|
116
|
+
*/
|
|
117
|
+
removeTenant(tenantId) {
|
|
118
|
+
return this.tenants.delete(tenantId);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Get tenant count.
|
|
123
|
+
*/
|
|
124
|
+
get size() {
|
|
125
|
+
return this.tenants.size;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// =========================================================================
|
|
130
|
+
// Role-Based Policies
|
|
131
|
+
// =========================================================================
|
|
132
|
+
|
|
133
|
+
const DEFAULT_ROLES = {
|
|
134
|
+
admin: {
|
|
135
|
+
name: 'Administrator',
|
|
136
|
+
sensitivity: 'medium',
|
|
137
|
+
blockOnThreat: false,
|
|
138
|
+
allowedTools: '*',
|
|
139
|
+
blockedTools: [],
|
|
140
|
+
bypassCircuitBreaker: true,
|
|
141
|
+
canViewAuditTrail: true,
|
|
142
|
+
canModifyPolicy: true
|
|
143
|
+
},
|
|
144
|
+
operator: {
|
|
145
|
+
name: 'Operator',
|
|
146
|
+
sensitivity: 'high',
|
|
147
|
+
blockOnThreat: true,
|
|
148
|
+
allowedTools: ['search', 'readFile', 'calculator'],
|
|
149
|
+
blockedTools: ['bash', 'shell', 'exec'],
|
|
150
|
+
bypassCircuitBreaker: false,
|
|
151
|
+
canViewAuditTrail: true,
|
|
152
|
+
canModifyPolicy: false
|
|
153
|
+
},
|
|
154
|
+
user: {
|
|
155
|
+
name: 'Standard User',
|
|
156
|
+
sensitivity: 'high',
|
|
157
|
+
blockOnThreat: true,
|
|
158
|
+
allowedTools: ['search', 'calculator'],
|
|
159
|
+
blockedTools: ['bash', 'shell', 'exec', 'readFile', 'writeFile'],
|
|
160
|
+
bypassCircuitBreaker: false,
|
|
161
|
+
canViewAuditTrail: false,
|
|
162
|
+
canModifyPolicy: false
|
|
163
|
+
},
|
|
164
|
+
restricted: {
|
|
165
|
+
name: 'Restricted User',
|
|
166
|
+
sensitivity: 'high',
|
|
167
|
+
blockOnThreat: true,
|
|
168
|
+
blockThreshold: 'low',
|
|
169
|
+
allowedTools: [],
|
|
170
|
+
blockedTools: '*',
|
|
171
|
+
bypassCircuitBreaker: false,
|
|
172
|
+
canViewAuditTrail: false,
|
|
173
|
+
canModifyPolicy: false
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
class RoleBasedPolicy {
|
|
178
|
+
constructor(options = {}) {
|
|
179
|
+
this.roles = { ...DEFAULT_ROLES, ...(options.customRoles || {}) };
|
|
180
|
+
this.userRoles = new Map();
|
|
181
|
+
this.shields = new Map();
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Assign a role to a user.
|
|
186
|
+
*/
|
|
187
|
+
assignRole(userId, role) {
|
|
188
|
+
if (!this.roles[role]) {
|
|
189
|
+
throw new Error(`Unknown role: ${role}. Available: ${Object.keys(this.roles).join(', ')}`);
|
|
190
|
+
}
|
|
191
|
+
this.userRoles.set(userId, role);
|
|
192
|
+
|
|
193
|
+
// Create a shield for this role if not exists
|
|
194
|
+
if (!this.shields.has(role)) {
|
|
195
|
+
const roleConfig = this.roles[role];
|
|
196
|
+
this.shields.set(role, new AgentShield({
|
|
197
|
+
sensitivity: roleConfig.sensitivity,
|
|
198
|
+
blockOnThreat: roleConfig.blockOnThreat,
|
|
199
|
+
blockThreshold: roleConfig.blockThreshold
|
|
200
|
+
}));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* Get the effective policy for a user.
|
|
208
|
+
*/
|
|
209
|
+
getPolicy(userId) {
|
|
210
|
+
const role = this.userRoles.get(userId) || 'user';
|
|
211
|
+
return { role, ...this.roles[role] };
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Scan input with the user's role-based policy.
|
|
216
|
+
*/
|
|
217
|
+
scan(userId, text, options = {}) {
|
|
218
|
+
const role = this.userRoles.get(userId) || 'user';
|
|
219
|
+
|
|
220
|
+
// Reuse shield created in assignRole, or create lazily
|
|
221
|
+
if (!this.shields.has(role)) {
|
|
222
|
+
this.assignRole(userId, role);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const result = this.shields.get(role).scan(text, options);
|
|
226
|
+
return { ...result, userId, role };
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Check if a user can use a specific tool.
|
|
231
|
+
*/
|
|
232
|
+
checkToolAccess(userId, toolName) {
|
|
233
|
+
const role = this.userRoles.get(userId) || 'user';
|
|
234
|
+
const roleConfig = this.roles[role];
|
|
235
|
+
|
|
236
|
+
if (roleConfig.blockedTools === '*') return { allowed: false, reason: 'All tools blocked for this role' };
|
|
237
|
+
if (Array.isArray(roleConfig.blockedTools) && roleConfig.blockedTools.includes(toolName)) {
|
|
238
|
+
return { allowed: false, reason: `Tool "${toolName}" is blocked for role "${role}"` };
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (roleConfig.allowedTools === '*') return { allowed: true };
|
|
242
|
+
if (Array.isArray(roleConfig.allowedTools) && roleConfig.allowedTools.includes(toolName)) {
|
|
243
|
+
return { allowed: true };
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
return { allowed: false, reason: `Tool "${toolName}" is not in the allowed list for role "${role}"` };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/**
|
|
250
|
+
* Define a custom role.
|
|
251
|
+
*/
|
|
252
|
+
defineRole(name, config) {
|
|
253
|
+
this.roles[name] = { name: config.name || name, ...config };
|
|
254
|
+
return this;
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Get all available roles.
|
|
259
|
+
*/
|
|
260
|
+
getRoles() {
|
|
261
|
+
return Object.entries(this.roles).map(([key, val]) => ({ key, ...val }));
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// =========================================================================
|
|
266
|
+
// Debug Mode
|
|
267
|
+
// =========================================================================
|
|
268
|
+
|
|
269
|
+
class DebugShield {
|
|
270
|
+
constructor(options = {}) {
|
|
271
|
+
this.shield = new AgentShield(options);
|
|
272
|
+
this.traces = [];
|
|
273
|
+
this.enabled = options.debug !== false;
|
|
274
|
+
this.maxTraces = options.maxTraces || 1000;
|
|
275
|
+
this.verbose = options.verbose || false;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Scan with full debug trace.
|
|
280
|
+
*/
|
|
281
|
+
scan(text, options = {}) {
|
|
282
|
+
const startTime = this.enabled ? process.hrtime.bigint() : null;
|
|
283
|
+
|
|
284
|
+
// Scan
|
|
285
|
+
const result = this.shield.scan(text, options);
|
|
286
|
+
|
|
287
|
+
// Only build trace if debug is enabled
|
|
288
|
+
let trace = null;
|
|
289
|
+
if (this.enabled) {
|
|
290
|
+
const endTime = process.hrtime.bigint();
|
|
291
|
+
const elapsedMs = Number(endTime - startTime) / 1e6;
|
|
292
|
+
|
|
293
|
+
trace = {
|
|
294
|
+
id: `trace_${Date.now()}_${Math.random().toString(36).slice(2, 8).padEnd(6, '0')}`,
|
|
295
|
+
timestamp: new Date().toISOString(),
|
|
296
|
+
input: text.substring(0, 500),
|
|
297
|
+
inputLength: text.length,
|
|
298
|
+
options,
|
|
299
|
+
steps: [
|
|
300
|
+
{
|
|
301
|
+
step: 'input_received',
|
|
302
|
+
time: 0,
|
|
303
|
+
detail: { length: text.length, hasUnicode: /[^\x00-\x7F]/.test(text) }
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
step: 'pattern_matching',
|
|
307
|
+
time: elapsedMs,
|
|
308
|
+
detail: {
|
|
309
|
+
patternsChecked: this.shield.getPatterns().length,
|
|
310
|
+
threatsFound: result.threats.length,
|
|
311
|
+
threats: result.threats.map(t => ({
|
|
312
|
+
severity: t.severity,
|
|
313
|
+
category: t.category,
|
|
314
|
+
description: t.description,
|
|
315
|
+
confidence: t.confidence
|
|
316
|
+
}))
|
|
317
|
+
}
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
step: 'decision',
|
|
321
|
+
time: elapsedMs,
|
|
322
|
+
detail: {
|
|
323
|
+
status: result.status,
|
|
324
|
+
blocked: result.blocked,
|
|
325
|
+
threatCount: result.threats.length
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
],
|
|
329
|
+
totalTimeMs: parseFloat(elapsedMs.toFixed(3)),
|
|
330
|
+
result: {
|
|
331
|
+
status: result.status,
|
|
332
|
+
blocked: result.blocked,
|
|
333
|
+
threatCount: result.threats.length
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
|
|
337
|
+
this.traces.push(trace);
|
|
338
|
+
while (this.traces.length > this.maxTraces) {
|
|
339
|
+
this.traces.shift();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (this.verbose) {
|
|
344
|
+
const ms = trace ? trace.totalTimeMs : 0;
|
|
345
|
+
console.log(`[Agent Shield] DEBUG Scan: ${text.substring(0, 50)}... → ${result.status} (${ms.toFixed(1)}ms, ${result.threats.length} threats)`);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return { ...result, _trace: trace };
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Get all traces.
|
|
353
|
+
*/
|
|
354
|
+
getTraces() {
|
|
355
|
+
return this.traces;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Get the last N traces.
|
|
360
|
+
*/
|
|
361
|
+
getRecentTraces(n = 10) {
|
|
362
|
+
return this.traces.slice(-n);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Export traces as JSON.
|
|
367
|
+
*/
|
|
368
|
+
exportTraces() {
|
|
369
|
+
return JSON.stringify(this.traces, null, 2);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Clear traces.
|
|
374
|
+
*/
|
|
375
|
+
clearTraces() {
|
|
376
|
+
this.traces = [];
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* Get timing statistics across all traces.
|
|
381
|
+
*/
|
|
382
|
+
getTimingStats() {
|
|
383
|
+
if (this.traces.length === 0) return null;
|
|
384
|
+
|
|
385
|
+
const times = this.traces.map(t => t.totalTimeMs);
|
|
386
|
+
times.sort((a, b) => a - b);
|
|
387
|
+
|
|
388
|
+
return {
|
|
389
|
+
count: times.length,
|
|
390
|
+
min: times[0],
|
|
391
|
+
max: times[times.length - 1],
|
|
392
|
+
avg: parseFloat((times.reduce((a, b) => a + b, 0) / times.length).toFixed(3)),
|
|
393
|
+
median: times[Math.floor(times.length / 2)],
|
|
394
|
+
p95: times[Math.min(Math.floor(times.length * 0.95), times.length - 1)],
|
|
395
|
+
p99: times[Math.min(Math.floor(times.length * 0.99), times.length - 1)]
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
module.exports = {
|
|
401
|
+
MultiTenantShield,
|
|
402
|
+
RoleBasedPolicy,
|
|
403
|
+
DebugShield,
|
|
404
|
+
DEFAULT_ROLES
|
|
405
|
+
};
|
package/src/errors.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Structured error codes for Agent Shield
|
|
5
|
+
* Format: AS-{CATEGORY}-{NUMBER}
|
|
6
|
+
*
|
|
7
|
+
* Categories:
|
|
8
|
+
* DET — Detection engine errors
|
|
9
|
+
* CFG — Configuration errors
|
|
10
|
+
* PLG — Plugin errors
|
|
11
|
+
* INT — Integration errors
|
|
12
|
+
* POL — Policy errors
|
|
13
|
+
* NET — Network/distributed errors
|
|
14
|
+
* AUT — Authentication/authorization errors
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
const ERROR_CODES = {
|
|
18
|
+
// Detection
|
|
19
|
+
'AS-DET-001': { message: 'Detection engine not initialized', severity: 'critical' },
|
|
20
|
+
'AS-DET-002': { message: 'Invalid input type — expected string', severity: 'high' },
|
|
21
|
+
'AS-DET-003': { message: 'Pattern compilation failed', severity: 'high' },
|
|
22
|
+
'AS-DET-004': { message: 'Scan timeout exceeded', severity: 'medium' },
|
|
23
|
+
'AS-DET-005': { message: 'Input exceeds maximum length', severity: 'medium' },
|
|
24
|
+
|
|
25
|
+
// Configuration
|
|
26
|
+
'AS-CFG-001': { message: 'Invalid configuration object', severity: 'critical' },
|
|
27
|
+
'AS-CFG-002': { message: 'Unknown configuration key', severity: 'low' },
|
|
28
|
+
'AS-CFG-003': { message: 'Invalid threshold value — must be 0-1', severity: 'high' },
|
|
29
|
+
'AS-CFG-004': { message: 'Preset not found', severity: 'medium' },
|
|
30
|
+
|
|
31
|
+
// Plugin
|
|
32
|
+
'AS-PLG-001': { message: 'Plugin failed to load', severity: 'high' },
|
|
33
|
+
'AS-PLG-002': { message: 'Plugin version incompatible', severity: 'high' },
|
|
34
|
+
'AS-PLG-003': { message: 'Plugin hook threw an error', severity: 'medium' },
|
|
35
|
+
|
|
36
|
+
// Integration
|
|
37
|
+
'AS-INT-001': { message: 'Framework adapter not found', severity: 'high' },
|
|
38
|
+
'AS-INT-002': { message: 'Middleware setup failed', severity: 'critical' },
|
|
39
|
+
'AS-INT-003': { message: 'Hook registration failed', severity: 'medium' },
|
|
40
|
+
|
|
41
|
+
// Policy
|
|
42
|
+
'AS-POL-001': { message: 'Policy parse error', severity: 'critical' },
|
|
43
|
+
'AS-POL-002': { message: 'Policy rule conflict detected', severity: 'high' },
|
|
44
|
+
'AS-POL-003': { message: 'Policy file not found', severity: 'high' },
|
|
45
|
+
|
|
46
|
+
// Network/Distributed
|
|
47
|
+
'AS-NET-001': { message: 'Distributed sync failed', severity: 'high' },
|
|
48
|
+
'AS-NET-002': { message: 'Peer node unreachable', severity: 'medium' },
|
|
49
|
+
|
|
50
|
+
// Auth
|
|
51
|
+
'AS-AUT-001': { message: 'RBAC permission denied', severity: 'high' },
|
|
52
|
+
'AS-AUT-002': { message: 'Tenant not found', severity: 'high' },
|
|
53
|
+
'AS-AUT-003': { message: 'SSO token validation failed', severity: 'critical' },
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Create a structured AgentShield error
|
|
58
|
+
* @param {string} code - Error code (e.g., 'AS-DET-001')
|
|
59
|
+
* @param {Object} [details] - Additional context
|
|
60
|
+
* @returns {Error}
|
|
61
|
+
*/
|
|
62
|
+
function createShieldError(code, details = {}) {
|
|
63
|
+
const entry = ERROR_CODES[code];
|
|
64
|
+
if (!entry) {
|
|
65
|
+
const err = new Error(`Unknown error code: ${code}`);
|
|
66
|
+
err.code = 'AS-CFG-002';
|
|
67
|
+
return err;
|
|
68
|
+
}
|
|
69
|
+
const err = new Error(`[Agent Shield ${code}] ${entry.message}`);
|
|
70
|
+
err.code = code;
|
|
71
|
+
err.severity = entry.severity;
|
|
72
|
+
err.details = details;
|
|
73
|
+
err.timestamp = Date.now();
|
|
74
|
+
return err;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Emit a deprecation warning (once per code)
|
|
79
|
+
* @param {string} feature - Deprecated feature name
|
|
80
|
+
* @param {string} replacement - Suggested replacement
|
|
81
|
+
* @param {string} removeVersion - Version when it will be removed
|
|
82
|
+
*/
|
|
83
|
+
const _warned = new Set();
|
|
84
|
+
function deprecationWarning(feature, replacement, removeVersion) {
|
|
85
|
+
const key = `${feature}:${replacement}`;
|
|
86
|
+
if (_warned.has(key)) return;
|
|
87
|
+
_warned.add(key);
|
|
88
|
+
const msg = `[Agent Shield] DEPRECATED: "${feature}" is deprecated and will be removed in v${removeVersion}. Use "${replacement}" instead.`;
|
|
89
|
+
if (typeof process !== 'undefined' && process.emitWarning) {
|
|
90
|
+
process.emitWarning(msg, 'DeprecationWarning');
|
|
91
|
+
} else {
|
|
92
|
+
console.warn(msg); // [Agent Shield] prefix included in msg
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = {
|
|
97
|
+
ERROR_CODES,
|
|
98
|
+
createShieldError,
|
|
99
|
+
deprecationWarning,
|
|
100
|
+
};
|