snow-flow 3.5.17 → 3.6.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.
@@ -0,0 +1,267 @@
1
+ "use strict";
2
+ /**
3
+ * ServiceNow Audit Logger - Snow-Flow Activity Tracking
4
+ *
5
+ * Extends the existing MCPLogger to send comprehensive audit logs
6
+ * to ServiceNow for all Snow-Flow activities with token usage tracking.
7
+ *
8
+ * Creates audit trail with source 'snow-flow' for compliance & debugging.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ServiceNowAuditLogger = void 0;
12
+ exports.getAuditLogger = getAuditLogger;
13
+ exports.initializeAuditLogging = initializeAuditLogging;
14
+ class ServiceNowAuditLogger {
15
+ constructor(mcpLogger, mcpServerName) {
16
+ this.isEnabled = true;
17
+ this.auditQueue = [];
18
+ this.mcpLogger = mcpLogger;
19
+ this.mcpServerName = mcpServerName;
20
+ this.sessionId = this.generateSessionId();
21
+ // Enable audit logging if not explicitly disabled
22
+ this.isEnabled = process.env.SNOW_FLOW_AUDIT_LOGGING !== 'false';
23
+ if (this.isEnabled) {
24
+ this.mcpLogger.info('🔍 ServiceNow Audit Logger initialized', {
25
+ source: 'snow-flow',
26
+ session_id: this.sessionId,
27
+ mcp_server: this.mcpServerName
28
+ });
29
+ }
30
+ }
31
+ /**
32
+ * Initialize with ServiceNow client for audit log transmission
33
+ */
34
+ setServiceNowClient(client) {
35
+ this.serviceNowClient = client;
36
+ if (this.isEnabled) {
37
+ this.mcpLogger.info('🔗 ServiceNow client connected for audit logging');
38
+ }
39
+ }
40
+ /**
41
+ * Generate unique session ID for tracking related operations
42
+ */
43
+ generateSessionId() {
44
+ return `snow-flow-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
45
+ }
46
+ /**
47
+ * Log Snow-Flow operation with comprehensive audit trail
48
+ */
49
+ async logOperation(operation, level = 'INFO', details = {}) {
50
+ if (!this.isEnabled)
51
+ return;
52
+ const tokenUsage = this.mcpLogger.getTokenUsage();
53
+ const timestamp = new Date().toISOString();
54
+ const auditEntry = {
55
+ source: 'snow-flow',
56
+ level,
57
+ message: details.message || `Snow-Flow ${operation}`,
58
+ operation,
59
+ table: details.table,
60
+ sys_id: details.sys_id,
61
+ token_usage: tokenUsage.total > 0 ? tokenUsage : undefined,
62
+ duration_ms: details.duration_ms,
63
+ metadata: {
64
+ ...details.metadata,
65
+ success: details.success,
66
+ mcp_server: this.mcpServerName,
67
+ session_id: this.sessionId
68
+ },
69
+ timestamp,
70
+ session_id: this.sessionId,
71
+ mcp_server: this.mcpServerName
72
+ };
73
+ // Log to console immediately via MCPLogger
74
+ this.mcpLogger.info(`🔍 [AUDIT] ${operation}`, auditEntry);
75
+ // Queue for ServiceNow transmission
76
+ this.auditQueue.push(auditEntry);
77
+ // Batch send to avoid overwhelming ServiceNow
78
+ this.scheduleBatchSend();
79
+ }
80
+ /**
81
+ * Log API call with token tracking
82
+ */
83
+ async logAPICall(apiMethod, table, operation, recordCount, duration_ms, success = true) {
84
+ await this.logOperation('api_call', success ? 'INFO' : 'ERROR', {
85
+ message: `API ${apiMethod} on ${table} (${recordCount || 0} records)`,
86
+ table,
87
+ duration_ms,
88
+ metadata: {
89
+ api_method: apiMethod,
90
+ record_count: recordCount,
91
+ operation
92
+ },
93
+ success
94
+ });
95
+ }
96
+ /**
97
+ * Log widget operations with specific tracking
98
+ */
99
+ async logWidgetOperation(operation, widgetSysId, widgetName, duration_ms, success = true, errorDetails) {
100
+ await this.logOperation('widget_operation', success ? 'INFO' : 'ERROR', {
101
+ message: `Widget ${operation}: ${widgetName || widgetSysId}`,
102
+ table: 'sp_widget',
103
+ sys_id: widgetSysId,
104
+ duration_ms,
105
+ metadata: {
106
+ widget_name: widgetName,
107
+ operation_type: operation,
108
+ error_details: errorDetails
109
+ },
110
+ success
111
+ });
112
+ }
113
+ /**
114
+ * Log artifact sync operations
115
+ */
116
+ async logArtifactSync(action, table, sys_id, artifactName, fileCount, duration_ms, success = true) {
117
+ await this.logOperation('artifact_sync', success ? 'INFO' : 'ERROR', {
118
+ message: `Artifact ${action}: ${artifactName || sys_id} (${fileCount || 0} files)`,
119
+ table,
120
+ sys_id,
121
+ duration_ms,
122
+ metadata: {
123
+ action,
124
+ artifact_name: artifactName,
125
+ file_count: fileCount
126
+ },
127
+ success
128
+ });
129
+ }
130
+ /**
131
+ * Log script execution with ES5 validation
132
+ */
133
+ async logScriptExecution(scriptType, duration_ms, success = true, errorDetails, outputLines) {
134
+ await this.logOperation('script_execution', success ? 'INFO' : 'ERROR', {
135
+ message: `Script execution: ${scriptType}`,
136
+ duration_ms,
137
+ metadata: {
138
+ script_type: scriptType,
139
+ output_lines: outputLines,
140
+ error_details: errorDetails,
141
+ es5_validated: true // Snow-Flow always uses ES5
142
+ },
143
+ success
144
+ });
145
+ }
146
+ /**
147
+ * Log authentication and token operations
148
+ */
149
+ async logAuthOperation(operation, success = true, details) {
150
+ await this.logOperation('authentication', success ? 'INFO' : 'WARN', {
151
+ message: `Auth ${operation}`,
152
+ metadata: {
153
+ operation,
154
+ ...details
155
+ },
156
+ success
157
+ });
158
+ }
159
+ /**
160
+ * Schedule batch sending to ServiceNow to avoid API flooding
161
+ */
162
+ scheduleBatchSend() {
163
+ if (this.batchTimer) {
164
+ clearTimeout(this.batchTimer);
165
+ }
166
+ // Send batches every 10 seconds or when queue reaches 20 entries
167
+ const shouldSendImmediately = this.auditQueue.length >= 20;
168
+ const delay = shouldSendImmediately ? 0 : 10000;
169
+ this.batchTimer = setTimeout(() => {
170
+ this.sendAuditBatch();
171
+ }, delay);
172
+ }
173
+ /**
174
+ * Send audit log batch to ServiceNow
175
+ */
176
+ async sendAuditBatch() {
177
+ if (this.auditQueue.length === 0 || !this.serviceNowClient) {
178
+ return;
179
+ }
180
+ const batch = [...this.auditQueue];
181
+ this.auditQueue = []; // Clear queue
182
+ try {
183
+ // Send to ServiceNow sys_log table with source 'snow-flow'
184
+ for (const entry of batch) {
185
+ await this.serviceNowClient.createRecord('sys_log', {
186
+ source: 'snow-flow',
187
+ level: entry.level,
188
+ message: entry.message,
189
+ sys_created_on: entry.timestamp,
190
+ // Custom fields for Snow-Flow specific data
191
+ u_operation: entry.operation,
192
+ u_table: entry.table,
193
+ u_sys_id: entry.sys_id,
194
+ u_session_id: entry.session_id,
195
+ u_mcp_server: entry.mcp_server,
196
+ u_token_usage: entry.token_usage ? JSON.stringify(entry.token_usage) : null,
197
+ u_duration_ms: entry.duration_ms,
198
+ u_metadata: entry.metadata ? JSON.stringify(entry.metadata) : null
199
+ });
200
+ }
201
+ this.mcpLogger.info(`📨 Sent ${batch.length} audit log entries to ServiceNow`);
202
+ }
203
+ catch (error) {
204
+ // If ServiceNow logging fails, log locally but don't fail the operation
205
+ this.mcpLogger.warn('Failed to send audit logs to ServiceNow', {
206
+ error: error instanceof Error ? error.message : String(error),
207
+ batch_size: batch.length
208
+ });
209
+ // Re-queue failed entries (with max retry limit)
210
+ const retriedEntries = batch.map(entry => ({
211
+ ...entry,
212
+ metadata: {
213
+ ...entry.metadata,
214
+ retry_count: (entry.metadata?.retry_count || 0) + 1
215
+ }
216
+ })).filter(entry => (entry.metadata?.retry_count || 0) < 3);
217
+ this.auditQueue.unshift(...retriedEntries);
218
+ }
219
+ }
220
+ /**
221
+ * Flush all pending audit logs immediately
222
+ */
223
+ async flush() {
224
+ if (this.batchTimer) {
225
+ clearTimeout(this.batchTimer);
226
+ this.batchTimer = undefined;
227
+ }
228
+ await this.sendAuditBatch();
229
+ }
230
+ /**
231
+ * Create audit logger wrapper for existing MCP server
232
+ */
233
+ static wrap(mcpLogger, mcpServerName) {
234
+ return new ServiceNowAuditLogger(mcpLogger, mcpServerName);
235
+ }
236
+ /**
237
+ * Get audit statistics
238
+ */
239
+ getAuditStats() {
240
+ return {
241
+ session_id: this.sessionId,
242
+ pending_logs: this.auditQueue.length,
243
+ is_enabled: this.isEnabled,
244
+ has_servicenow_client: !!this.serviceNowClient
245
+ };
246
+ }
247
+ }
248
+ exports.ServiceNowAuditLogger = ServiceNowAuditLogger;
249
+ /**
250
+ * Global audit logger factory for consistent usage across MCP servers
251
+ */
252
+ const auditLoggers = new Map();
253
+ function getAuditLogger(mcpLogger, mcpServerName) {
254
+ if (!auditLoggers.has(mcpServerName)) {
255
+ auditLoggers.set(mcpServerName, new ServiceNowAuditLogger(mcpLogger, mcpServerName));
256
+ }
257
+ return auditLoggers.get(mcpServerName);
258
+ }
259
+ /**
260
+ * Initialize all audit loggers with ServiceNow client
261
+ */
262
+ function initializeAuditLogging(serviceNowClient) {
263
+ auditLoggers.forEach(logger => {
264
+ logger.setServiceNowClient(serviceNowClient);
265
+ });
266
+ }
267
+ //# sourceMappingURL=servicenow-audit-logger.js.map
@@ -6,6 +6,10 @@ import { MCPLogger } from '../mcp/shared/mcp-logger.js';
6
6
  export declare class ServiceNowClientWithTracking extends ServiceNowClient {
7
7
  private mcpLogger;
8
8
  constructor(logger?: MCPLogger);
9
+ /**
10
+ * Get the base ServiceNow client for audit logger integration
11
+ */
12
+ getBaseClient(): ServiceNowClient;
9
13
  /**
10
14
  * Override makeRequest to add tracking
11
15
  */
@@ -11,6 +11,12 @@ class ServiceNowClientWithTracking extends servicenow_client_js_1.ServiceNowClie
11
11
  super();
12
12
  this.mcpLogger = logger || new mcp_logger_js_1.MCPLogger('ServiceNow-API');
13
13
  }
14
+ /**
15
+ * Get the base ServiceNow client for audit logger integration
16
+ */
17
+ getBaseClient() {
18
+ return this;
19
+ }
14
20
  /**
15
21
  * Override makeRequest to add tracking
16
22
  */
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "snow-flow",
3
- "version": "3.5.17",
4
- "description": "ServiceNow development framework with ROBUST artifact detection fix. v3.5.17 FIXES the intermittent 'Could not find artifact' errors in snow_pull_artifact. Enhanced pullArtifactBySysId with detailed error logging, longer timeouts (8s per table), smart table ordering, and comprehensive troubleshooting guidance. ULTRA-CONSERVATIVE wrapper system prevents duplicate HTML comments. Enhanced 'snow-flow init' creates optimized settings.json with 18 MCP servers, extensive development permissions, intelligent hooks, and ServiceNow-specific commands. Features intelligent timeout configuration and comprehensive ServiceNow development workflow.",
3
+ "version": "3.6.1",
4
+ "description": "ServiceNow development framework with ABSOLUTE NO MOCK DATA POLICY. v3.6.1 enforces COMPLETE, PRODUCTION-READY implementations with NO placeholders, NO TODO comments, NO test data, and NO shortcuts. EVERY implementation must be fully functional. Enhanced CLAUDE.md template with comprehensive examples of complete implementations. Includes comprehensive audit logging with source 'snow-flow', token tracking, and compliance support. Features robust artifact detection, ultra-conservative wrapper system, and 18 MCP servers. TAKE THE TIME. DO IT RIGHT. NO EXCEPTIONS.",
5
5
  "main": "dist/index.js",
6
6
  "type": "commonjs",
7
7
  "bin": {