openclaw-observability 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.
- package/dist/config.d.ts +60 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +140 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +1114 -0
- package/dist/index.js.map +1 -0
- package/dist/redaction.d.ts +20 -0
- package/dist/redaction.d.ts.map +1 -0
- package/dist/redaction.js +93 -0
- package/dist/redaction.js.map +1 -0
- package/dist/security/chain-detector.d.ts +37 -0
- package/dist/security/chain-detector.d.ts.map +1 -0
- package/dist/security/chain-detector.js +187 -0
- package/dist/security/chain-detector.js.map +1 -0
- package/dist/security/rules.d.ts +22 -0
- package/dist/security/rules.d.ts.map +1 -0
- package/dist/security/rules.js +479 -0
- package/dist/security/rules.js.map +1 -0
- package/dist/security/scanner.d.ts +47 -0
- package/dist/security/scanner.d.ts.map +1 -0
- package/dist/security/scanner.js +150 -0
- package/dist/security/scanner.js.map +1 -0
- package/dist/security/types.d.ts +47 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/types.js +23 -0
- package/dist/security/types.js.map +1 -0
- package/dist/storage/buffer.d.ts +64 -0
- package/dist/storage/buffer.d.ts.map +1 -0
- package/dist/storage/buffer.js +120 -0
- package/dist/storage/buffer.js.map +1 -0
- package/dist/storage/duckdb-local-writer.d.ts +26 -0
- package/dist/storage/duckdb-local-writer.d.ts.map +1 -0
- package/dist/storage/duckdb-local-writer.js +454 -0
- package/dist/storage/duckdb-local-writer.js.map +1 -0
- package/dist/storage/mysql-writer.d.ts +55 -0
- package/dist/storage/mysql-writer.d.ts.map +1 -0
- package/dist/storage/mysql-writer.js +287 -0
- package/dist/storage/mysql-writer.js.map +1 -0
- package/dist/storage/schema.d.ts +13 -0
- package/dist/storage/schema.d.ts.map +1 -0
- package/dist/storage/schema.js +94 -0
- package/dist/storage/schema.js.map +1 -0
- package/dist/storage/writer.d.ts +31 -0
- package/dist/storage/writer.d.ts.map +1 -0
- package/dist/storage/writer.js +7 -0
- package/dist/storage/writer.js.map +1 -0
- package/dist/types.d.ts +72 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +44 -0
- package/dist/types.js.map +1 -0
- package/dist/web/api.d.ts +115 -0
- package/dist/web/api.d.ts.map +1 -0
- package/dist/web/api.js +219 -0
- package/dist/web/api.js.map +1 -0
- package/dist/web/routes.d.ts +20 -0
- package/dist/web/routes.d.ts.map +1 -0
- package/dist/web/routes.js +175 -0
- package/dist/web/routes.js.map +1 -0
- package/dist/web/ui.d.ts +9 -0
- package/dist/web/ui.d.ts.map +1 -0
- package/dist/web/ui.js +1327 -0
- package/dist/web/ui.js.map +1 -0
- package/openclaw.plugin.json +231 -0
- package/package.json +41 -0
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* DuckDB local write layer
|
|
4
|
+
* Uses embedded DuckDB (@duckdb/node-api), zero-config out of the box
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
18
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
19
|
+
}) : function(o, v) {
|
|
20
|
+
o["default"] = v;
|
|
21
|
+
});
|
|
22
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
23
|
+
var ownKeys = function(o) {
|
|
24
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
25
|
+
var ar = [];
|
|
26
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
27
|
+
return ar;
|
|
28
|
+
};
|
|
29
|
+
return ownKeys(o);
|
|
30
|
+
};
|
|
31
|
+
return function (mod) {
|
|
32
|
+
if (mod && mod.__esModule) return mod;
|
|
33
|
+
var result = {};
|
|
34
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
35
|
+
__setModuleDefault(result, mod);
|
|
36
|
+
return result;
|
|
37
|
+
};
|
|
38
|
+
})();
|
|
39
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
40
|
+
exports.DuckDBLocalWriter = void 0;
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const fs = __importStar(require("fs"));
|
|
43
|
+
/* ------------------------------------------------------------------ */
|
|
44
|
+
/* @duckdb/node-api Promise wrapper -> QueryPool adapter */
|
|
45
|
+
/* ------------------------------------------------------------------ */
|
|
46
|
+
/**
|
|
47
|
+
* Wraps @duckdb/node-api as QueryPool interface
|
|
48
|
+
* Return format compatible with mysql2: [rowObjects[], null]
|
|
49
|
+
*/
|
|
50
|
+
class DuckDBPool {
|
|
51
|
+
conn;
|
|
52
|
+
instance;
|
|
53
|
+
constructor(instance, conn) {
|
|
54
|
+
this.instance = instance;
|
|
55
|
+
this.conn = conn;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Execute query and return [rowObjects[], null]
|
|
59
|
+
* Compatible with mysql2 Pool.query() return format
|
|
60
|
+
*/
|
|
61
|
+
async query(sql, params) {
|
|
62
|
+
// Replace ? placeholders with $1, $2, ... format (DuckDB uses $N)
|
|
63
|
+
let duckSql = sql;
|
|
64
|
+
if (params && params.length > 0) {
|
|
65
|
+
let idx = 0;
|
|
66
|
+
duckSql = sql.replace(/\?/g, () => `$${++idx}`);
|
|
67
|
+
}
|
|
68
|
+
// Use parameterized query or direct execution
|
|
69
|
+
if (params && params.length > 0) {
|
|
70
|
+
const stmt = await this.conn.prepare(duckSql);
|
|
71
|
+
this._bindParams(stmt, params);
|
|
72
|
+
const result = await stmt.runAndReadAll();
|
|
73
|
+
const rows = this._toRowObjects(result);
|
|
74
|
+
return [rows, null];
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
const result = await this.conn.runAndReadAll(duckSql);
|
|
78
|
+
const rows = this._toRowObjects(result);
|
|
79
|
+
return [rows, null];
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
/** Execute SQL without returning results (DDL / INSERT / UPDATE) */
|
|
83
|
+
async exec(sql) {
|
|
84
|
+
// Execute one statement at a time (DuckDB run doesn't support multiple semicolons)
|
|
85
|
+
const statements = sql
|
|
86
|
+
.split(';')
|
|
87
|
+
.map(s => s.trim())
|
|
88
|
+
.filter(s => s.length > 0);
|
|
89
|
+
for (const stmt of statements) {
|
|
90
|
+
await this.conn.run(stmt);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
/** Execute parameterized INSERT/UPDATE (no return value) */
|
|
94
|
+
async run(sql, params) {
|
|
95
|
+
let duckSql = sql;
|
|
96
|
+
if (params && params.length > 0) {
|
|
97
|
+
let idx = 0;
|
|
98
|
+
duckSql = sql.replace(/\?/g, () => `$${++idx}`);
|
|
99
|
+
}
|
|
100
|
+
if (params && params.length > 0) {
|
|
101
|
+
const stmt = await this.conn.prepare(duckSql);
|
|
102
|
+
this._bindParams(stmt, params);
|
|
103
|
+
await stmt.run();
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
await this.conn.run(duckSql);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/** Close connection and instance */
|
|
110
|
+
async close() {
|
|
111
|
+
try {
|
|
112
|
+
// @duckdb/node-api: explicitly disconnect
|
|
113
|
+
if (this.conn && typeof this.conn.disconnect === 'function') {
|
|
114
|
+
await this.conn.disconnect();
|
|
115
|
+
}
|
|
116
|
+
else if (this.conn && typeof this.conn.close === 'function') {
|
|
117
|
+
await this.conn.close();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// Ignore close errors
|
|
122
|
+
}
|
|
123
|
+
this.conn = null;
|
|
124
|
+
this.instance = null;
|
|
125
|
+
}
|
|
126
|
+
/* ---- Internal helpers ---- */
|
|
127
|
+
/** Bind parameters to prepared statement */
|
|
128
|
+
_bindParams(stmt, params) {
|
|
129
|
+
for (let i = 0; i < params.length; i++) {
|
|
130
|
+
const paramIdx = i + 1; // 1-based
|
|
131
|
+
const val = params[i];
|
|
132
|
+
if (val === null || val === undefined) {
|
|
133
|
+
stmt.bindNull(paramIdx);
|
|
134
|
+
}
|
|
135
|
+
else if (typeof val === 'number') {
|
|
136
|
+
if (Number.isInteger(val)) {
|
|
137
|
+
stmt.bindInteger(paramIdx, val);
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
stmt.bindDouble(paramIdx, val);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else if (typeof val === 'string') {
|
|
144
|
+
stmt.bindVarchar(paramIdx, val);
|
|
145
|
+
}
|
|
146
|
+
else if (typeof val === 'boolean') {
|
|
147
|
+
stmt.bindBoolean(paramIdx, val);
|
|
148
|
+
}
|
|
149
|
+
else if (val instanceof Date) {
|
|
150
|
+
stmt.bindVarchar(paramIdx, val.toISOString().replace('T', ' ').slice(0, 19));
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
// Other types: convert to string
|
|
154
|
+
stmt.bindVarchar(paramIdx, String(val));
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
/** Convert DuckDB row array results to row objects (compatible with mysql2 RowDataPacket) */
|
|
159
|
+
_toRowObjects(result) {
|
|
160
|
+
const columnNames = result.columnNames();
|
|
161
|
+
const rawRows = result.getRows();
|
|
162
|
+
return rawRows.map((row) => {
|
|
163
|
+
const obj = {};
|
|
164
|
+
for (let i = 0; i < columnNames.length; i++) {
|
|
165
|
+
obj[columnNames[i]] = this._convertValue(row[i]);
|
|
166
|
+
}
|
|
167
|
+
return obj;
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
/** Convert DuckDB special types to standard JS types */
|
|
171
|
+
_convertValue(val) {
|
|
172
|
+
if (val === null || val === undefined)
|
|
173
|
+
return null;
|
|
174
|
+
if (typeof val === 'bigint')
|
|
175
|
+
return Number(val);
|
|
176
|
+
// DuckDBTimestampValue -> ISO string
|
|
177
|
+
if (val && typeof val === 'object' && 'micros' in val) {
|
|
178
|
+
const micros = val.micros;
|
|
179
|
+
const ms = typeof micros === 'bigint' ? Number(micros / 1000n) : Number(micros) / 1000;
|
|
180
|
+
return new Date(ms).toISOString().replace('T', ' ').slice(0, 19);
|
|
181
|
+
}
|
|
182
|
+
// DuckDBDateValue -> string
|
|
183
|
+
if (val && typeof val === 'object' && 'days' in val) {
|
|
184
|
+
const days = val.days;
|
|
185
|
+
const ms = (typeof days === 'bigint' ? Number(days) : days) * 86400000;
|
|
186
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
187
|
+
}
|
|
188
|
+
return val;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
/* ------------------------------------------------------------------ */
|
|
192
|
+
/* DuckDB Schema */
|
|
193
|
+
/* WARNING: MySQL schema is defined in schema.ts. */
|
|
194
|
+
/* When modifying table structure, update both places. */
|
|
195
|
+
/* ------------------------------------------------------------------ */
|
|
196
|
+
const DUCKDB_SCHEMA_STATEMENTS = [
|
|
197
|
+
`CREATE SEQUENCE IF NOT EXISTS audit_actions_id_seq`,
|
|
198
|
+
`CREATE TABLE IF NOT EXISTS audit_actions (
|
|
199
|
+
id BIGINT DEFAULT nextval('audit_actions_id_seq') PRIMARY KEY,
|
|
200
|
+
session_id VARCHAR(64) NOT NULL,
|
|
201
|
+
action_type VARCHAR(32) NOT NULL,
|
|
202
|
+
action_name VARCHAR(255) NOT NULL,
|
|
203
|
+
model_name VARCHAR(128) DEFAULT '',
|
|
204
|
+
input_params TEXT,
|
|
205
|
+
output_result TEXT,
|
|
206
|
+
prompt_tokens INTEGER DEFAULT NULL,
|
|
207
|
+
completion_tokens INTEGER DEFAULT NULL,
|
|
208
|
+
duration_ms INTEGER DEFAULT NULL,
|
|
209
|
+
user_id VARCHAR(128) DEFAULT '',
|
|
210
|
+
created_at TIMESTAMP DEFAULT current_timestamp
|
|
211
|
+
)`,
|
|
212
|
+
`CREATE INDEX IF NOT EXISTS idx_act_session ON audit_actions(session_id)`,
|
|
213
|
+
`CREATE INDEX IF NOT EXISTS idx_act_type ON audit_actions(action_type)`,
|
|
214
|
+
`CREATE INDEX IF NOT EXISTS idx_act_created ON audit_actions(created_at)`,
|
|
215
|
+
`CREATE INDEX IF NOT EXISTS idx_act_user ON audit_actions(user_id)`,
|
|
216
|
+
`CREATE TABLE IF NOT EXISTS audit_sessions (
|
|
217
|
+
session_id VARCHAR(64) PRIMARY KEY,
|
|
218
|
+
user_id VARCHAR(128) DEFAULT '',
|
|
219
|
+
model_name VARCHAR(128) DEFAULT '',
|
|
220
|
+
start_time TIMESTAMP NOT NULL,
|
|
221
|
+
end_time TIMESTAMP DEFAULT NULL,
|
|
222
|
+
total_actions INTEGER DEFAULT 0,
|
|
223
|
+
total_tokens INTEGER DEFAULT 0
|
|
224
|
+
)`,
|
|
225
|
+
`CREATE INDEX IF NOT EXISTS idx_ses_user ON audit_sessions(user_id)`,
|
|
226
|
+
`CREATE INDEX IF NOT EXISTS idx_ses_start ON audit_sessions(start_time)`,
|
|
227
|
+
`CREATE SEQUENCE IF NOT EXISTS audit_alerts_id_seq`,
|
|
228
|
+
`CREATE TABLE IF NOT EXISTS audit_alerts (
|
|
229
|
+
id BIGINT DEFAULT nextval('audit_alerts_id_seq') PRIMARY KEY,
|
|
230
|
+
alert_id VARCHAR(64) NOT NULL,
|
|
231
|
+
session_id VARCHAR(64) NOT NULL,
|
|
232
|
+
action_type VARCHAR(32) NOT NULL,
|
|
233
|
+
action_name VARCHAR(256) DEFAULT '',
|
|
234
|
+
rule_id VARCHAR(32) NOT NULL,
|
|
235
|
+
rule_name VARCHAR(128) NOT NULL,
|
|
236
|
+
category VARCHAR(32) NOT NULL,
|
|
237
|
+
severity VARCHAR(16) NOT NULL,
|
|
238
|
+
finding TEXT,
|
|
239
|
+
context TEXT,
|
|
240
|
+
status VARCHAR(16) DEFAULT 'open',
|
|
241
|
+
resolved_by VARCHAR(128) DEFAULT NULL,
|
|
242
|
+
resolved_at TIMESTAMP DEFAULT NULL,
|
|
243
|
+
user_id VARCHAR(128) DEFAULT '',
|
|
244
|
+
model_name VARCHAR(128) DEFAULT '',
|
|
245
|
+
created_at TIMESTAMP DEFAULT current_timestamp
|
|
246
|
+
)`,
|
|
247
|
+
`CREATE INDEX IF NOT EXISTS idx_alrt_sev ON audit_alerts(severity)`,
|
|
248
|
+
`CREATE INDEX IF NOT EXISTS idx_alrt_cat ON audit_alerts(category)`,
|
|
249
|
+
`CREATE INDEX IF NOT EXISTS idx_alrt_sta ON audit_alerts(status)`,
|
|
250
|
+
`CREATE INDEX IF NOT EXISTS idx_alrt_ses ON audit_alerts(session_id)`,
|
|
251
|
+
`CREATE INDEX IF NOT EXISTS idx_alrt_cre ON audit_alerts(created_at)`,
|
|
252
|
+
`CREATE INDEX IF NOT EXISTS idx_alrt_rul ON audit_alerts(rule_id)`,
|
|
253
|
+
];
|
|
254
|
+
/* ------------------------------------------------------------------ */
|
|
255
|
+
/* Writer implementation */
|
|
256
|
+
/* ------------------------------------------------------------------ */
|
|
257
|
+
class DuckDBLocalWriter {
|
|
258
|
+
pool = null;
|
|
259
|
+
config;
|
|
260
|
+
initialized = false;
|
|
261
|
+
initializing = false;
|
|
262
|
+
constructor(config) {
|
|
263
|
+
this.config = config;
|
|
264
|
+
}
|
|
265
|
+
async initialize(maxRetries = 3, retryDelayMs = 2000) {
|
|
266
|
+
if (this.initialized)
|
|
267
|
+
return;
|
|
268
|
+
if (this.initializing)
|
|
269
|
+
return;
|
|
270
|
+
this.initializing = true;
|
|
271
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
272
|
+
try {
|
|
273
|
+
await this._doInitialize();
|
|
274
|
+
this.initializing = false;
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
catch (error) {
|
|
278
|
+
console.error(`[audit-duckdb] DuckDB init attempt ${attempt}/${maxRetries} failed:`, error.message || error);
|
|
279
|
+
if (attempt < maxRetries) {
|
|
280
|
+
await new Promise(r => setTimeout(r, retryDelayMs));
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
this.initializing = false;
|
|
285
|
+
throw new Error('All DuckDB initialization attempts failed');
|
|
286
|
+
}
|
|
287
|
+
async ensureReady() {
|
|
288
|
+
if (this.initialized && this.pool)
|
|
289
|
+
return true;
|
|
290
|
+
try {
|
|
291
|
+
await this.initialize(1, 0);
|
|
292
|
+
return this.initialized;
|
|
293
|
+
}
|
|
294
|
+
catch {
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
async _doInitialize() {
|
|
299
|
+
// Dynamically load @duckdb/node-api
|
|
300
|
+
let duckdb;
|
|
301
|
+
try {
|
|
302
|
+
duckdb = require('@duckdb/node-api');
|
|
303
|
+
}
|
|
304
|
+
catch {
|
|
305
|
+
throw new Error('@duckdb/node-api package not installed. Run: npm install @duckdb/node-api\n' +
|
|
306
|
+
'Or switch to remote mode: set mode = "remote" in plugin config.');
|
|
307
|
+
}
|
|
308
|
+
// Ensure parent directory exists
|
|
309
|
+
const dbPath = this.config.path;
|
|
310
|
+
if (dbPath !== ':memory:') {
|
|
311
|
+
const dir = path.dirname(dbPath);
|
|
312
|
+
if (!fs.existsSync(dir)) {
|
|
313
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
// Open database
|
|
317
|
+
const instance = await duckdb.DuckDBInstance.create(dbPath);
|
|
318
|
+
const conn = await instance.connect();
|
|
319
|
+
this.pool = new DuckDBPool(instance, conn);
|
|
320
|
+
// Create table schema (execute one statement at a time)
|
|
321
|
+
for (const stmt of DUCKDB_SCHEMA_STATEMENTS) {
|
|
322
|
+
await this.pool.run(stmt);
|
|
323
|
+
}
|
|
324
|
+
this.initialized = true;
|
|
325
|
+
console.log(`[audit-duckdb] DuckDB writer initialized: ${dbPath}`);
|
|
326
|
+
}
|
|
327
|
+
/* ---- Write ---- */
|
|
328
|
+
async writeBatch(entries) {
|
|
329
|
+
if (!this.pool || !this.initialized) {
|
|
330
|
+
throw new Error('DuckDB writer not initialized');
|
|
331
|
+
}
|
|
332
|
+
const actions = entries.filter(e => e.type === 'action').map(e => e.data);
|
|
333
|
+
const sessions = entries.filter(e => e.type === 'session').map(e => e.data);
|
|
334
|
+
if (actions.length > 0)
|
|
335
|
+
await this.writeActions(actions);
|
|
336
|
+
if (sessions.length > 0)
|
|
337
|
+
await this.writeSessions(sessions);
|
|
338
|
+
}
|
|
339
|
+
async writeActions(actions) {
|
|
340
|
+
if (!this.pool)
|
|
341
|
+
return;
|
|
342
|
+
const sql = `
|
|
343
|
+
INSERT INTO audit_actions
|
|
344
|
+
(session_id, action_type, action_name, model_name, input_params, output_result,
|
|
345
|
+
prompt_tokens, completion_tokens, duration_ms, user_id, created_at)
|
|
346
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
347
|
+
`;
|
|
348
|
+
for (const a of actions) {
|
|
349
|
+
await this.pool.run(sql, [
|
|
350
|
+
a.sessionId, a.actionType, a.actionName, a.modelName,
|
|
351
|
+
a.inputParams ? JSON.stringify(a.inputParams) : null,
|
|
352
|
+
a.outputResult ? JSON.stringify(a.outputResult) : null,
|
|
353
|
+
a.promptTokens, a.completionTokens, a.durationMs,
|
|
354
|
+
a.userId,
|
|
355
|
+
a.createdAt instanceof Date
|
|
356
|
+
? a.createdAt.toISOString().replace('T', ' ').slice(0, 19)
|
|
357
|
+
: String(a.createdAt),
|
|
358
|
+
]);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
async writeSessions(sessions) {
|
|
362
|
+
if (!this.pool)
|
|
363
|
+
return;
|
|
364
|
+
// Deduplicate within same batch
|
|
365
|
+
const deduped = new Map();
|
|
366
|
+
for (const s of sessions)
|
|
367
|
+
deduped.set(s.sessionId, s);
|
|
368
|
+
for (const session of deduped.values()) {
|
|
369
|
+
// Aggregate stats from audit_actions in real-time
|
|
370
|
+
const [statsRows] = await this.pool.query(`SELECT
|
|
371
|
+
MIN(created_at) AS start_time,
|
|
372
|
+
MAX(created_at) AS end_time,
|
|
373
|
+
COUNT(*) AS total_actions,
|
|
374
|
+
COALESCE(SUM(COALESCE(prompt_tokens, 0) + COALESCE(completion_tokens, 0)), 0) AS total_tokens
|
|
375
|
+
FROM audit_actions WHERE session_id = ?`, [session.sessionId]);
|
|
376
|
+
const stats = statsRows[0];
|
|
377
|
+
const startTime = stats?.start_time || this._formatDate(session.startTime);
|
|
378
|
+
const endTime = stats?.end_time || this._formatDate(session.endTime);
|
|
379
|
+
const totalActions = Number(stats?.total_actions) || 0;
|
|
380
|
+
const totalTokens = Number(stats?.total_tokens) || 0;
|
|
381
|
+
// Check if session already exists
|
|
382
|
+
const [existingRows] = await this.pool.query('SELECT session_id, start_time, user_id FROM audit_sessions WHERE session_id = ?', [session.sessionId]);
|
|
383
|
+
const existing = existingRows[0];
|
|
384
|
+
if (existing) {
|
|
385
|
+
const earlierStart = existing.start_time && startTime && new Date(existing.start_time) < new Date(startTime)
|
|
386
|
+
? existing.start_time : startTime;
|
|
387
|
+
await this.pool.run(`UPDATE audit_sessions
|
|
388
|
+
SET user_id = ?,
|
|
389
|
+
model_name = CASE WHEN ? != '' THEN ? ELSE model_name END,
|
|
390
|
+
start_time = CAST(? AS TIMESTAMP),
|
|
391
|
+
end_time = CAST(? AS TIMESTAMP),
|
|
392
|
+
total_actions = ?,
|
|
393
|
+
total_tokens = ?
|
|
394
|
+
WHERE session_id = ?`, [
|
|
395
|
+
session.userId || existing.user_id || '',
|
|
396
|
+
session.modelName, session.modelName,
|
|
397
|
+
earlierStart, endTime,
|
|
398
|
+
totalActions, totalTokens,
|
|
399
|
+
session.sessionId,
|
|
400
|
+
]);
|
|
401
|
+
}
|
|
402
|
+
else {
|
|
403
|
+
await this.pool.run(`INSERT INTO audit_sessions
|
|
404
|
+
(session_id, user_id, model_name, start_time, end_time, total_actions, total_tokens)
|
|
405
|
+
VALUES (?, ?, ?, CAST(? AS TIMESTAMP), CAST(? AS TIMESTAMP), ?, ?)`, [
|
|
406
|
+
session.sessionId,
|
|
407
|
+
session.userId, session.modelName,
|
|
408
|
+
this._formatDate(session.startTime), this._formatDate(session.endTime),
|
|
409
|
+
totalActions, totalTokens,
|
|
410
|
+
]);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
async writeAlerts(alerts) {
|
|
415
|
+
if (!this.pool || alerts.length === 0)
|
|
416
|
+
return;
|
|
417
|
+
const sql = `
|
|
418
|
+
INSERT INTO audit_alerts
|
|
419
|
+
(alert_id, session_id, action_type, action_name, rule_id, rule_name,
|
|
420
|
+
category, severity, finding, context, status, user_id, model_name, created_at)
|
|
421
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
422
|
+
`;
|
|
423
|
+
for (const a of alerts) {
|
|
424
|
+
await this.pool.run(sql, [
|
|
425
|
+
a.alertId, a.sessionId, a.actionType, a.actionName,
|
|
426
|
+
a.ruleId, a.ruleName, a.category, a.severity,
|
|
427
|
+
a.finding, a.context, a.status,
|
|
428
|
+
a.userId, a.modelName, a.createdAt,
|
|
429
|
+
]);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
/* ---- Query / Lifecycle ---- */
|
|
433
|
+
getPool() {
|
|
434
|
+
return this.pool;
|
|
435
|
+
}
|
|
436
|
+
async close() {
|
|
437
|
+
if (this.pool) {
|
|
438
|
+
await this.pool.close();
|
|
439
|
+
this.pool = null;
|
|
440
|
+
this.initialized = false;
|
|
441
|
+
console.log('[audit-duckdb] DuckDB writer closed');
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
/* ---- Helpers ---- */
|
|
445
|
+
_formatDate(d) {
|
|
446
|
+
if (!d)
|
|
447
|
+
return new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
448
|
+
if (d instanceof Date)
|
|
449
|
+
return d.toISOString().replace('T', ' ').slice(0, 19);
|
|
450
|
+
return String(d);
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
exports.DuckDBLocalWriter = DuckDBLocalWriter;
|
|
454
|
+
//# sourceMappingURL=duckdb-local-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"duckdb-local-writer.js","sourceRoot":"","sources":["../../src/storage/duckdb-local-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MySQL write layer
|
|
3
|
+
* Writes audit records to MySQL-compatible database
|
|
4
|
+
*/
|
|
5
|
+
import { MySQLConfig } from '../config';
|
|
6
|
+
import { SecurityAlert } from '../security/types';
|
|
7
|
+
import { BufferEntry } from './buffer';
|
|
8
|
+
import { QueryPool, AuditWriter } from './writer';
|
|
9
|
+
/**
|
|
10
|
+
* MySQL writer
|
|
11
|
+
* Manages connection pool and data writing
|
|
12
|
+
*/
|
|
13
|
+
export declare class MySQLWriter implements AuditWriter {
|
|
14
|
+
private pool;
|
|
15
|
+
private config;
|
|
16
|
+
private initialized;
|
|
17
|
+
private initializing;
|
|
18
|
+
constructor(config: MySQLConfig);
|
|
19
|
+
/**
|
|
20
|
+
* Initialize connection pool and schema (with retries)
|
|
21
|
+
*/
|
|
22
|
+
initialize(maxRetries?: number, retryDelayMs?: number): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Lazy initialization — auto-connect on query
|
|
25
|
+
*/
|
|
26
|
+
ensureReady(): Promise<boolean>;
|
|
27
|
+
private _doInitialize;
|
|
28
|
+
/**
|
|
29
|
+
* Batch write buffer entries
|
|
30
|
+
*/
|
|
31
|
+
writeBatch(entries: BufferEntry[]): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Batch insert audit action records
|
|
34
|
+
*/
|
|
35
|
+
private writeActions;
|
|
36
|
+
/**
|
|
37
|
+
* Write or update session summary records
|
|
38
|
+
* Stats are aggregated in real-time from audit_actions, not from memory counters
|
|
39
|
+
* This ensures historical data is preserved even after Gateway restarts
|
|
40
|
+
*/
|
|
41
|
+
private writeSessions;
|
|
42
|
+
/**
|
|
43
|
+
* Write security alert records
|
|
44
|
+
*/
|
|
45
|
+
writeAlerts(alerts: SecurityAlert[]): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Get connection pool (for Web API queries)
|
|
48
|
+
*/
|
|
49
|
+
getPool(): QueryPool | null;
|
|
50
|
+
/**
|
|
51
|
+
* Close connection pool
|
|
52
|
+
*/
|
|
53
|
+
close(): Promise<void>;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=mysql-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mysql-writer.d.ts","sourceRoot":"","sources":["../../src/storage/mysql-writer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAExC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAElD;;;GAGG;AACH,qBAAa,WAAY,YAAW,WAAW;IAC7C,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAc;IAC5B,OAAO,CAAC,WAAW,CAAkB;IACrC,OAAO,CAAC,YAAY,CAAkB;gBAE1B,MAAM,EAAE,WAAW;IAI/B;;OAEG;IACG,UAAU,CAAC,UAAU,SAAI,EAAE,YAAY,SAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IA2BrE;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;YAUvB,aAAa;IA6C3B;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBvD;;OAEG;YACW,YAAY;IAgC1B;;;;OAIG;YACW,aAAa;IAuF3B;;OAEG;IACG,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAmCzD;;OAEG;IACH,OAAO,IAAI,SAAS,GAAG,IAAI;IAI3B;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B"}
|