guardrail-core 1.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.
Files changed (189) hide show
  1. package/dist/__tests__/autopilot.test.d.ts +7 -0
  2. package/dist/__tests__/autopilot.test.d.ts.map +1 -0
  3. package/dist/__tests__/autopilot.test.js +156 -0
  4. package/dist/__tests__/tier-config.test.d.ts +9 -0
  5. package/dist/__tests__/tier-config.test.d.ts.map +1 -0
  6. package/dist/__tests__/tier-config.test.js +230 -0
  7. package/dist/__tests__/utils/hash-inline.test.d.ts +2 -0
  8. package/dist/__tests__/utils/hash-inline.test.d.ts.map +1 -0
  9. package/dist/__tests__/utils/hash-inline.test.js +62 -0
  10. package/dist/__tests__/utils/hash.test.d.ts +3 -0
  11. package/dist/__tests__/utils/hash.test.d.ts.map +1 -0
  12. package/dist/__tests__/utils/hash.test.js +95 -0
  13. package/dist/__tests__/utils/simple.test.d.ts +1 -0
  14. package/dist/__tests__/utils/simple.test.d.ts.map +1 -0
  15. package/dist/__tests__/utils/simple.test.js +10 -0
  16. package/dist/__tests__/utils/utils-simple.test.d.ts +1 -0
  17. package/dist/__tests__/utils/utils-simple.test.d.ts.map +1 -0
  18. package/dist/__tests__/utils/utils-simple.test.js +6 -0
  19. package/dist/__tests__/utils/utils.test.d.ts +15 -0
  20. package/dist/__tests__/utils/utils.test.d.ts.map +1 -0
  21. package/dist/__tests__/utils/utils.test.js +172 -0
  22. package/dist/autopilot/autopilot-runner.d.ts +33 -0
  23. package/dist/autopilot/autopilot-runner.d.ts.map +1 -0
  24. package/dist/autopilot/autopilot-runner.js +479 -0
  25. package/dist/autopilot/index.d.ts +6 -0
  26. package/dist/autopilot/index.d.ts.map +1 -0
  27. package/dist/autopilot/index.js +25 -0
  28. package/dist/autopilot/types.d.ts +102 -0
  29. package/dist/autopilot/types.d.ts.map +1 -0
  30. package/dist/autopilot/types.js +18 -0
  31. package/dist/cache/index.d.ts +7 -0
  32. package/dist/cache/index.d.ts.map +1 -0
  33. package/dist/cache/index.js +22 -0
  34. package/dist/cache/redis-cache.d.ts +145 -0
  35. package/dist/cache/redis-cache.d.ts.map +1 -0
  36. package/dist/cache/redis-cache.js +459 -0
  37. package/dist/ci/github-actions.d.ts +77 -0
  38. package/dist/ci/github-actions.d.ts.map +1 -0
  39. package/dist/ci/github-actions.js +277 -0
  40. package/dist/ci/index.d.ts +12 -0
  41. package/dist/ci/index.d.ts.map +1 -0
  42. package/dist/ci/index.js +27 -0
  43. package/dist/ci/pre-commit.d.ts +65 -0
  44. package/dist/ci/pre-commit.d.ts.map +1 -0
  45. package/dist/ci/pre-commit.js +286 -0
  46. package/dist/entitlements.d.ts +149 -0
  47. package/dist/entitlements.d.ts.map +1 -0
  48. package/dist/entitlements.js +464 -0
  49. package/dist/env.d.ts +113 -0
  50. package/dist/env.d.ts.map +1 -0
  51. package/dist/env.js +204 -0
  52. package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts +7 -0
  53. package/dist/fix-packs/__tests__/generate-fix-packs.test.d.ts.map +1 -0
  54. package/dist/fix-packs/__tests__/generate-fix-packs.test.js +250 -0
  55. package/dist/fix-packs/generate-fix-packs.d.ts +15 -0
  56. package/dist/fix-packs/generate-fix-packs.d.ts.map +1 -0
  57. package/dist/fix-packs/generate-fix-packs.js +505 -0
  58. package/dist/fix-packs/index.d.ts +8 -0
  59. package/dist/fix-packs/index.d.ts.map +1 -0
  60. package/dist/fix-packs/index.js +23 -0
  61. package/dist/fix-packs/types.d.ts +113 -0
  62. package/dist/fix-packs/types.d.ts.map +1 -0
  63. package/dist/fix-packs/types.js +71 -0
  64. package/dist/index.d.ts +13 -0
  65. package/dist/index.d.ts.map +1 -0
  66. package/dist/index.js +28 -0
  67. package/dist/metrics/prometheus.d.ts +99 -0
  68. package/dist/metrics/prometheus.d.ts.map +1 -0
  69. package/dist/metrics/prometheus.js +306 -0
  70. package/dist/quota-ledger.d.ts +119 -0
  71. package/dist/quota-ledger.d.ts.map +1 -0
  72. package/dist/quota-ledger.js +462 -0
  73. package/dist/rbac/__tests__/permissions.test.d.ts +8 -0
  74. package/dist/rbac/__tests__/permissions.test.d.ts.map +1 -0
  75. package/dist/rbac/__tests__/permissions.test.js +350 -0
  76. package/dist/rbac/index.d.ts +9 -0
  77. package/dist/rbac/index.d.ts.map +1 -0
  78. package/dist/rbac/index.js +32 -0
  79. package/dist/rbac/permissions.d.ts +71 -0
  80. package/dist/rbac/permissions.d.ts.map +1 -0
  81. package/dist/rbac/permissions.js +247 -0
  82. package/dist/rbac/types.d.ts +69 -0
  83. package/dist/rbac/types.d.ts.map +1 -0
  84. package/dist/rbac/types.js +213 -0
  85. package/dist/tier-config.d.ts +203 -0
  86. package/dist/tier-config.d.ts.map +1 -0
  87. package/dist/tier-config.js +675 -0
  88. package/dist/types.d.ts +365 -0
  89. package/dist/types.d.ts.map +1 -0
  90. package/dist/types.js +5 -0
  91. package/dist/utils.d.ts +36 -0
  92. package/dist/utils.d.ts.map +1 -0
  93. package/dist/utils.js +127 -0
  94. package/dist/verified-autofix/__tests__/format-validator.test.d.ts +11 -0
  95. package/dist/verified-autofix/__tests__/format-validator.test.d.ts.map +1 -0
  96. package/dist/verified-autofix/__tests__/format-validator.test.js +285 -0
  97. package/dist/verified-autofix/__tests__/pipeline.test.d.ts +11 -0
  98. package/dist/verified-autofix/__tests__/pipeline.test.d.ts.map +1 -0
  99. package/dist/verified-autofix/__tests__/pipeline.test.js +389 -0
  100. package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts +11 -0
  101. package/dist/verified-autofix/__tests__/repo-fingerprint.test.d.ts.map +1 -0
  102. package/dist/verified-autofix/__tests__/repo-fingerprint.test.js +236 -0
  103. package/dist/verified-autofix/__tests__/workspace.test.d.ts +11 -0
  104. package/dist/verified-autofix/__tests__/workspace.test.d.ts.map +1 -0
  105. package/dist/verified-autofix/__tests__/workspace.test.js +314 -0
  106. package/dist/verified-autofix/format-validator.d.ts +101 -0
  107. package/dist/verified-autofix/format-validator.d.ts.map +1 -0
  108. package/dist/verified-autofix/format-validator.js +446 -0
  109. package/dist/verified-autofix/index.d.ts +14 -0
  110. package/dist/verified-autofix/index.d.ts.map +1 -0
  111. package/dist/verified-autofix/index.js +39 -0
  112. package/dist/verified-autofix/pipeline.d.ts +68 -0
  113. package/dist/verified-autofix/pipeline.d.ts.map +1 -0
  114. package/dist/verified-autofix/pipeline.js +330 -0
  115. package/dist/verified-autofix/repo-fingerprint.d.ts +56 -0
  116. package/dist/verified-autofix/repo-fingerprint.d.ts.map +1 -0
  117. package/dist/verified-autofix/repo-fingerprint.js +396 -0
  118. package/dist/verified-autofix/workspace.d.ts +83 -0
  119. package/dist/verified-autofix/workspace.d.ts.map +1 -0
  120. package/dist/verified-autofix/workspace.js +454 -0
  121. package/dist/verified-autofix.d.ts +182 -0
  122. package/dist/verified-autofix.d.ts.map +1 -0
  123. package/dist/verified-autofix.js +1021 -0
  124. package/dist/visualization/dependency-graph.d.ts +79 -0
  125. package/dist/visualization/dependency-graph.d.ts.map +1 -0
  126. package/dist/visualization/dependency-graph.js +399 -0
  127. package/dist/visualization/index.d.ts +5 -0
  128. package/dist/visualization/index.d.ts.map +1 -0
  129. package/dist/visualization/index.js +20 -0
  130. package/package.json +29 -0
  131. package/src/__tests__/autopilot.test.ts +196 -0
  132. package/src/__tests__/tier-config.test.ts +289 -0
  133. package/src/__tests__/utils/hash-inline.test.ts +76 -0
  134. package/src/__tests__/utils/hash.test.ts +119 -0
  135. package/src/__tests__/utils/simple.test.ts +10 -0
  136. package/src/__tests__/utils/utils-simple.test.ts +5 -0
  137. package/src/__tests__/utils/utils.test.ts +203 -0
  138. package/src/autopilot/autopilot-runner.ts +503 -0
  139. package/src/autopilot/index.ts +6 -0
  140. package/src/autopilot/types.ts +119 -0
  141. package/src/cache/index.ts +7 -0
  142. package/src/cache/redis-cache.d.ts +155 -0
  143. package/src/cache/redis-cache.d.ts.map +1 -0
  144. package/src/cache/redis-cache.ts +517 -0
  145. package/src/ci/github-actions.ts +335 -0
  146. package/src/ci/index.ts +12 -0
  147. package/src/ci/pre-commit.ts +338 -0
  148. package/src/db/usage-schema.prisma +114 -0
  149. package/src/entitlements.ts +570 -0
  150. package/src/env.d.ts +68 -0
  151. package/src/env.d.ts.map +1 -0
  152. package/src/env.ts +247 -0
  153. package/src/fix-packs/__tests__/generate-fix-packs.test.ts +317 -0
  154. package/src/fix-packs/generate-fix-packs.ts +577 -0
  155. package/src/fix-packs/index.ts +8 -0
  156. package/src/fix-packs/types.ts +206 -0
  157. package/src/index.d.ts +7 -0
  158. package/src/index.d.ts.map +1 -0
  159. package/src/index.ts +12 -0
  160. package/src/metrics/prometheus.d.ts +104 -0
  161. package/src/metrics/prometheus.d.ts.map +1 -0
  162. package/src/metrics/prometheus.ts +446 -0
  163. package/src/quota-ledger.ts +548 -0
  164. package/src/rbac/__tests__/permissions.test.ts +446 -0
  165. package/src/rbac/index.ts +46 -0
  166. package/src/rbac/permissions.ts +301 -0
  167. package/src/rbac/types.ts +298 -0
  168. package/src/tier-config.json +157 -0
  169. package/src/tier-config.ts +815 -0
  170. package/src/types.d.ts +365 -0
  171. package/src/types.d.ts.map +1 -0
  172. package/src/types.ts +441 -0
  173. package/src/utils.d.ts +36 -0
  174. package/src/utils.d.ts.map +1 -0
  175. package/src/utils.ts +140 -0
  176. package/src/verified-autofix/__tests__/format-validator.test.ts +335 -0
  177. package/src/verified-autofix/__tests__/pipeline.test.ts +419 -0
  178. package/src/verified-autofix/__tests__/repo-fingerprint.test.ts +241 -0
  179. package/src/verified-autofix/__tests__/workspace.test.ts +373 -0
  180. package/src/verified-autofix/format-validator.ts +517 -0
  181. package/src/verified-autofix/index.ts +63 -0
  182. package/src/verified-autofix/pipeline.ts +403 -0
  183. package/src/verified-autofix/repo-fingerprint.ts +459 -0
  184. package/src/verified-autofix/workspace.ts +531 -0
  185. package/src/verified-autofix.ts +1187 -0
  186. package/src/visualization/dependency-graph.d.ts +85 -0
  187. package/src/visualization/dependency-graph.d.ts.map +1 -0
  188. package/src/visualization/dependency-graph.ts +495 -0
  189. package/src/visualization/index.ts +5 -0
@@ -0,0 +1,446 @@
1
+ /**
2
+ * Prometheus Metrics
3
+ *
4
+ * Production-ready metrics collection for Guardrail AI
5
+ * Exposes metrics in Prometheus format for monitoring and alerting
6
+ */
7
+
8
+ export interface MetricLabels {
9
+ [key: string]: string;
10
+ }
11
+
12
+ export interface MetricValue {
13
+ value: number;
14
+ labels: MetricLabels;
15
+ timestamp?: number;
16
+ }
17
+
18
+ export interface Metric {
19
+ name: string;
20
+ help: string;
21
+ type: "counter" | "gauge" | "histogram" | "summary";
22
+ values: MetricValue[];
23
+ }
24
+
25
+ class Counter {
26
+ private values: Map<string, number> = new Map();
27
+
28
+ constructor(
29
+ public readonly name: string,
30
+ public readonly help: string,
31
+ public readonly labelNames: string[] = [],
32
+ ) {}
33
+
34
+ inc(labels: MetricLabels = {}, value: number = 1): void {
35
+ const key = this.labelsToKey(labels);
36
+ const current = this.values.get(key) || 0;
37
+ this.values.set(key, current + value);
38
+ }
39
+
40
+ get(labels: MetricLabels = {}): number {
41
+ const key = this.labelsToKey(labels);
42
+ return this.values.get(key) || 0;
43
+ }
44
+
45
+ reset(): void {
46
+ this.values.clear();
47
+ }
48
+
49
+ collect(): MetricValue[] {
50
+ const result: MetricValue[] = [];
51
+ for (const [key, value] of this.values) {
52
+ result.push({
53
+ value,
54
+ labels: this.keyToLabels(key),
55
+ });
56
+ }
57
+ return result;
58
+ }
59
+
60
+ private labelsToKey(labels: MetricLabels): string {
61
+ return this.labelNames.map((name) => labels[name] || "").join("|");
62
+ }
63
+
64
+ private keyToLabels(key: string): MetricLabels {
65
+ const values = key.split("|");
66
+ const labels: MetricLabels = {};
67
+ this.labelNames.forEach((name, i) => {
68
+ if (values[i]) {
69
+ labels[name] = values[i];
70
+ }
71
+ });
72
+ return labels;
73
+ }
74
+ }
75
+
76
+ class Gauge {
77
+ private values: Map<string, number> = new Map();
78
+
79
+ constructor(
80
+ public readonly name: string,
81
+ public readonly help: string,
82
+ public readonly labelNames: string[] = [],
83
+ ) {}
84
+
85
+ set(labels: MetricLabels, value: number): void;
86
+ set(value: number): void;
87
+ set(labelsOrValue: MetricLabels | number, value?: number): void {
88
+ if (typeof labelsOrValue === "number") {
89
+ this.values.set("", labelsOrValue);
90
+ } else {
91
+ const key = this.labelsToKey(labelsOrValue);
92
+ this.values.set(key, value!);
93
+ }
94
+ }
95
+
96
+ inc(labels: MetricLabels = {}, value: number = 1): void {
97
+ const key = this.labelsToKey(labels);
98
+ const current = this.values.get(key) || 0;
99
+ this.values.set(key, current + value);
100
+ }
101
+
102
+ dec(labels: MetricLabels = {}, value: number = 1): void {
103
+ const key = this.labelsToKey(labels);
104
+ const current = this.values.get(key) || 0;
105
+ this.values.set(key, current - value);
106
+ }
107
+
108
+ get(labels: MetricLabels = {}): number {
109
+ const key = this.labelsToKey(labels);
110
+ return this.values.get(key) || 0;
111
+ }
112
+
113
+ collect(): MetricValue[] {
114
+ const result: MetricValue[] = [];
115
+ for (const [key, value] of this.values) {
116
+ result.push({
117
+ value,
118
+ labels: this.keyToLabels(key),
119
+ });
120
+ }
121
+ return result;
122
+ }
123
+
124
+ private labelsToKey(labels: MetricLabels): string {
125
+ return this.labelNames.map((name) => labels[name] || "").join("|");
126
+ }
127
+
128
+ private keyToLabels(key: string): MetricLabels {
129
+ const values = key.split("|");
130
+ const labels: MetricLabels = {};
131
+ this.labelNames.forEach((name, i) => {
132
+ if (values[i]) {
133
+ labels[name] = values[i];
134
+ }
135
+ });
136
+ return labels;
137
+ }
138
+ }
139
+
140
+ class Histogram {
141
+ private buckets: number[];
142
+ private values: Map<
143
+ string,
144
+ { sum: number; count: number; buckets: number[] }
145
+ > = new Map();
146
+
147
+ constructor(
148
+ public readonly name: string,
149
+ public readonly help: string,
150
+ public readonly labelNames: string[] = [],
151
+ buckets?: number[],
152
+ ) {
153
+ this.buckets = buckets || [
154
+ 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10,
155
+ ];
156
+ }
157
+
158
+ observe(labels: MetricLabels, value: number): void;
159
+ observe(value: number): void;
160
+ observe(labelsOrValue: MetricLabels | number, value?: number): void {
161
+ let labels: MetricLabels;
162
+ let observedValue: number;
163
+
164
+ if (typeof labelsOrValue === "number") {
165
+ labels = {};
166
+ observedValue = labelsOrValue;
167
+ } else {
168
+ labels = labelsOrValue;
169
+ observedValue = value!;
170
+ }
171
+
172
+ const key = this.labelsToKey(labels);
173
+ let data = this.values.get(key);
174
+
175
+ if (!data) {
176
+ data = {
177
+ sum: 0,
178
+ count: 0,
179
+ buckets: new Array(this.buckets.length).fill(0),
180
+ };
181
+ this.values.set(key, data);
182
+ }
183
+
184
+ data.sum += observedValue;
185
+ data.count++;
186
+
187
+ for (let i = 0; i < this.buckets.length; i++) {
188
+ const bucket = this.buckets[i];
189
+ if (bucket !== undefined && observedValue <= bucket) {
190
+ // @ts-ignore
191
+ data.buckets[i]++;
192
+ }
193
+ }
194
+ }
195
+
196
+ startTimer(labels: MetricLabels = {}): () => number {
197
+ const start = process.hrtime.bigint();
198
+ return () => {
199
+ const end = process.hrtime.bigint();
200
+ const durationMs = Number(end - start) / 1e6;
201
+ this.observe(labels, durationMs / 1000); // Convert to seconds
202
+ return durationMs;
203
+ };
204
+ }
205
+
206
+ collect(): MetricValue[] {
207
+ const result: MetricValue[] = [];
208
+
209
+ for (const [key, data] of this.values) {
210
+ const labels = this.keyToLabels(key);
211
+
212
+ // Add bucket values
213
+ for (let i = 0; i < this.buckets.length; i++) {
214
+ const bucketValue = data.buckets[i] ?? 0;
215
+ const bucketLimit = this.buckets[i] ?? 0;
216
+ result.push({
217
+ value: bucketValue,
218
+ labels: { ...labels, le: String(bucketLimit) },
219
+ });
220
+ }
221
+
222
+ // Add +Inf bucket
223
+ result.push({
224
+ value: data.count,
225
+ labels: { ...labels, le: "+Inf" },
226
+ });
227
+
228
+ // Add sum and count
229
+ result.push({
230
+ value: data.sum,
231
+ labels: { ...labels, quantile: "sum" },
232
+ });
233
+ result.push({
234
+ value: data.count,
235
+ labels: { ...labels, quantile: "count" },
236
+ });
237
+ }
238
+
239
+ return result;
240
+ }
241
+
242
+ private labelsToKey(labels: MetricLabels): string {
243
+ return this.labelNames.map((name) => labels[name] || "").join("|");
244
+ }
245
+
246
+ private keyToLabels(key: string): MetricLabels {
247
+ const values = key.split("|");
248
+ const labels: MetricLabels = {};
249
+ this.labelNames.forEach((name, i) => {
250
+ if (values[i]) {
251
+ labels[name] = values[i];
252
+ }
253
+ });
254
+ return labels;
255
+ }
256
+ }
257
+
258
+ /**
259
+ * Guardrail Metrics Registry
260
+ */
261
+ class MetricsRegistry {
262
+ // Scan metrics
263
+ readonly scansTotal = new Counter(
264
+ "Guardrail_scans_total",
265
+ "Total number of security scans performed",
266
+ ["scan_type", "status"],
267
+ );
268
+
269
+ readonly scanDuration = new Histogram(
270
+ "Guardrail_scan_duration_seconds",
271
+ "Duration of security scans in seconds",
272
+ ["scan_type"],
273
+ [0.1, 0.5, 1, 2, 5, 10, 30, 60],
274
+ );
275
+
276
+ // Injection detection metrics
277
+ readonly injectionsDetected = new Counter(
278
+ "Guardrail_injections_detected_total",
279
+ "Total number of prompt injection attempts detected",
280
+ ["severity", "type"],
281
+ );
282
+
283
+ readonly injectionScanDuration = new Histogram(
284
+ "Guardrail_injection_scan_duration_seconds",
285
+ "Duration of injection scans in seconds",
286
+ ["content_type"],
287
+ );
288
+
289
+ // Vulnerability metrics
290
+ readonly vulnerabilitiesFound = new Counter(
291
+ "Guardrail_vulnerabilities_found_total",
292
+ "Total number of vulnerabilities found",
293
+ ["severity", "source"],
294
+ );
295
+
296
+ readonly vulnerablePackages = new Gauge(
297
+ "Guardrail_vulnerable_packages",
298
+ "Current number of vulnerable packages",
299
+ ["project_id"],
300
+ );
301
+
302
+ // Secret detection metrics
303
+ readonly secretsDetected = new Counter(
304
+ "Guardrail_secrets_detected_total",
305
+ "Total number of secrets detected",
306
+ ["secret_type", "severity"],
307
+ );
308
+
309
+ // Compliance metrics
310
+ readonly complianceScore = new Gauge(
311
+ "Guardrail_compliance_score",
312
+ "Current compliance score (0-100)",
313
+ ["framework", "project_id"],
314
+ );
315
+
316
+ readonly complianceViolations = new Counter(
317
+ "Guardrail_compliance_violations_total",
318
+ "Total number of compliance violations",
319
+ ["framework", "severity"],
320
+ );
321
+
322
+ // API metrics
323
+ readonly apiRequestsTotal = new Counter(
324
+ "Guardrail_api_requests_total",
325
+ "Total number of API requests",
326
+ ["method", "endpoint", "status_code"],
327
+ );
328
+
329
+ readonly apiRequestDuration = new Histogram(
330
+ "Guardrail_api_request_duration_seconds",
331
+ "Duration of API requests in seconds",
332
+ ["method", "endpoint"],
333
+ );
334
+
335
+ // Agent metrics
336
+ readonly agentActionsTotal = new Counter(
337
+ "Guardrail_agent_actions_total",
338
+ "Total number of agent actions",
339
+ ["agent_id", "action_type", "status"],
340
+ );
341
+
342
+ readonly agentActionsBlocked = new Counter(
343
+ "Guardrail_agent_actions_blocked_total",
344
+ "Total number of agent actions blocked",
345
+ ["agent_id", "reason"],
346
+ );
347
+
348
+ // Cache metrics
349
+ readonly cacheHits = new Counter(
350
+ "Guardrail_cache_hits_total",
351
+ "Total number of cache hits",
352
+ ["cache_type"],
353
+ );
354
+
355
+ readonly cacheMisses = new Counter(
356
+ "Guardrail_cache_misses_total",
357
+ "Total number of cache misses",
358
+ ["cache_type"],
359
+ );
360
+
361
+ // System metrics
362
+ readonly activeConnections = new Gauge(
363
+ "Guardrail_active_connections",
364
+ "Number of active WebSocket connections",
365
+ [],
366
+ );
367
+
368
+ readonly memoryUsageBytes = new Gauge(
369
+ "Guardrail_memory_usage_bytes",
370
+ "Current memory usage in bytes",
371
+ ["type"],
372
+ );
373
+
374
+ /**
375
+ * Generate Prometheus-formatted output
376
+ */
377
+ generatePrometheusOutput(): string {
378
+ const lines: string[] = [];
379
+
380
+ const metrics = [
381
+ { metric: this.scansTotal, type: "counter" },
382
+ { metric: this.scanDuration, type: "histogram" },
383
+ { metric: this.injectionsDetected, type: "counter" },
384
+ { metric: this.injectionScanDuration, type: "histogram" },
385
+ { metric: this.vulnerabilitiesFound, type: "counter" },
386
+ { metric: this.vulnerablePackages, type: "gauge" },
387
+ { metric: this.secretsDetected, type: "counter" },
388
+ { metric: this.complianceScore, type: "gauge" },
389
+ { metric: this.complianceViolations, type: "counter" },
390
+ { metric: this.apiRequestsTotal, type: "counter" },
391
+ { metric: this.apiRequestDuration, type: "histogram" },
392
+ { metric: this.agentActionsTotal, type: "counter" },
393
+ { metric: this.agentActionsBlocked, type: "counter" },
394
+ { metric: this.cacheHits, type: "counter" },
395
+ { metric: this.cacheMisses, type: "counter" },
396
+ { metric: this.activeConnections, type: "gauge" },
397
+ { metric: this.memoryUsageBytes, type: "gauge" },
398
+ ];
399
+
400
+ for (const { metric, type } of metrics) {
401
+ lines.push(`# HELP ${metric.name} ${metric.help}`);
402
+ lines.push(`# TYPE ${metric.name} ${type}`);
403
+
404
+ const values = metric.collect();
405
+ for (const { value, labels } of values) {
406
+ const labelStr = Object.entries(labels)
407
+ .map(([k, v]) => `${k}="${v}"`)
408
+ .join(",");
409
+
410
+ if (labelStr) {
411
+ lines.push(`${metric.name}{${labelStr}} ${value}`);
412
+ } else {
413
+ lines.push(`${metric.name} ${value}`);
414
+ }
415
+ }
416
+ lines.push("");
417
+ }
418
+
419
+ return lines.join("\n");
420
+ }
421
+
422
+ /**
423
+ * Update system metrics
424
+ */
425
+ updateSystemMetrics(): void {
426
+ const memUsage = process.memoryUsage();
427
+ this.memoryUsageBytes.set({ type: "heap_used" }, memUsage.heapUsed);
428
+ this.memoryUsageBytes.set({ type: "heap_total" }, memUsage.heapTotal);
429
+ this.memoryUsageBytes.set({ type: "rss" }, memUsage.rss);
430
+ this.memoryUsageBytes.set({ type: "external" }, memUsage.external);
431
+ }
432
+
433
+ /**
434
+ * Reset all metrics (for testing)
435
+ */
436
+ resetAll(): void {
437
+ this.scansTotal.reset();
438
+ // Add reset for other metrics as needed
439
+ }
440
+ }
441
+
442
+ // Export singleton registry
443
+ export const metrics = new MetricsRegistry();
444
+
445
+ // Export classes for custom metrics
446
+ export { Counter, Gauge, Histogram };