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.
Files changed (66) hide show
  1. package/dist/config.d.ts +60 -0
  2. package/dist/config.d.ts.map +1 -0
  3. package/dist/config.js +140 -0
  4. package/dist/config.js.map +1 -0
  5. package/dist/index.d.ts +37 -0
  6. package/dist/index.d.ts.map +1 -0
  7. package/dist/index.js +1114 -0
  8. package/dist/index.js.map +1 -0
  9. package/dist/redaction.d.ts +20 -0
  10. package/dist/redaction.d.ts.map +1 -0
  11. package/dist/redaction.js +93 -0
  12. package/dist/redaction.js.map +1 -0
  13. package/dist/security/chain-detector.d.ts +37 -0
  14. package/dist/security/chain-detector.d.ts.map +1 -0
  15. package/dist/security/chain-detector.js +187 -0
  16. package/dist/security/chain-detector.js.map +1 -0
  17. package/dist/security/rules.d.ts +22 -0
  18. package/dist/security/rules.d.ts.map +1 -0
  19. package/dist/security/rules.js +479 -0
  20. package/dist/security/rules.js.map +1 -0
  21. package/dist/security/scanner.d.ts +47 -0
  22. package/dist/security/scanner.d.ts.map +1 -0
  23. package/dist/security/scanner.js +150 -0
  24. package/dist/security/scanner.js.map +1 -0
  25. package/dist/security/types.d.ts +47 -0
  26. package/dist/security/types.d.ts.map +1 -0
  27. package/dist/security/types.js +23 -0
  28. package/dist/security/types.js.map +1 -0
  29. package/dist/storage/buffer.d.ts +64 -0
  30. package/dist/storage/buffer.d.ts.map +1 -0
  31. package/dist/storage/buffer.js +120 -0
  32. package/dist/storage/buffer.js.map +1 -0
  33. package/dist/storage/duckdb-local-writer.d.ts +26 -0
  34. package/dist/storage/duckdb-local-writer.d.ts.map +1 -0
  35. package/dist/storage/duckdb-local-writer.js +454 -0
  36. package/dist/storage/duckdb-local-writer.js.map +1 -0
  37. package/dist/storage/mysql-writer.d.ts +55 -0
  38. package/dist/storage/mysql-writer.d.ts.map +1 -0
  39. package/dist/storage/mysql-writer.js +287 -0
  40. package/dist/storage/mysql-writer.js.map +1 -0
  41. package/dist/storage/schema.d.ts +13 -0
  42. package/dist/storage/schema.d.ts.map +1 -0
  43. package/dist/storage/schema.js +94 -0
  44. package/dist/storage/schema.js.map +1 -0
  45. package/dist/storage/writer.d.ts +31 -0
  46. package/dist/storage/writer.d.ts.map +1 -0
  47. package/dist/storage/writer.js +7 -0
  48. package/dist/storage/writer.js.map +1 -0
  49. package/dist/types.d.ts +72 -0
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +44 -0
  52. package/dist/types.js.map +1 -0
  53. package/dist/web/api.d.ts +115 -0
  54. package/dist/web/api.d.ts.map +1 -0
  55. package/dist/web/api.js +219 -0
  56. package/dist/web/api.js.map +1 -0
  57. package/dist/web/routes.d.ts +20 -0
  58. package/dist/web/routes.d.ts.map +1 -0
  59. package/dist/web/routes.js +175 -0
  60. package/dist/web/routes.js.map +1 -0
  61. package/dist/web/ui.d.ts +9 -0
  62. package/dist/web/ui.d.ts.map +1 -0
  63. package/dist/web/ui.js +1327 -0
  64. package/dist/web/ui.js.map +1 -0
  65. package/openclaw.plugin.json +231 -0
  66. package/package.json +41 -0
@@ -0,0 +1,150 @@
1
+ "use strict";
2
+ /**
3
+ * SecurityScanner — main entry point for security detection
4
+ * Coordinates L1 rule engine + L2 behavior chain detector
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.SecurityScanner = exports.DEFAULT_SECURITY_CONFIG = void 0;
8
+ exports.resolveSecurityConfig = resolveSecurityConfig;
9
+ const crypto_1 = require("crypto");
10
+ const types_1 = require("./types");
11
+ const rules_1 = require("./rules");
12
+ const chain_detector_1 = require("./chain-detector");
13
+ exports.DEFAULT_SECURITY_CONFIG = {
14
+ enabled: true,
15
+ rules: {
16
+ secretLeakage: true,
17
+ highRiskOps: true,
18
+ promptInjection: true,
19
+ chainDetection: true,
20
+ },
21
+ domainWhitelist: [],
22
+ };
23
+ function resolveSecurityConfig(raw) {
24
+ if (!raw)
25
+ return { ...exports.DEFAULT_SECURITY_CONFIG };
26
+ return {
27
+ enabled: raw.enabled ?? exports.DEFAULT_SECURITY_CONFIG.enabled,
28
+ rules: {
29
+ ...exports.DEFAULT_SECURITY_CONFIG.rules,
30
+ ...raw.rules,
31
+ },
32
+ domainWhitelist: raw.domainWhitelist ?? exports.DEFAULT_SECURITY_CONFIG.domainWhitelist,
33
+ };
34
+ }
35
+ /* ------------------------------------------------------------------ */
36
+ /* Scanner */
37
+ /* ------------------------------------------------------------------ */
38
+ /** Rule category -> config toggle mapping */
39
+ const CATEGORY_TOGGLE = {
40
+ [types_1.RuleCategory.SecretLeakage]: 'secretLeakage',
41
+ [types_1.RuleCategory.HighRiskOp]: 'highRiskOps',
42
+ [types_1.RuleCategory.DataExfil]: 'highRiskOps',
43
+ [types_1.RuleCategory.PromptInjection]: 'promptInjection',
44
+ [types_1.RuleCategory.SkillAnomaly]: 'highRiskOps',
45
+ };
46
+ class SecurityScanner {
47
+ rules;
48
+ chainDetector;
49
+ config;
50
+ /** Runtime context — passed to each rule's detect method */
51
+ ruleCtx;
52
+ /** Cumulative statistics */
53
+ stats = {
54
+ scanned: 0,
55
+ alertsGenerated: 0,
56
+ };
57
+ constructor(config) {
58
+ this.config = config;
59
+ // Filter rules based on config
60
+ this.rules = rules_1.ALL_RULES.filter(rule => {
61
+ const toggle = CATEGORY_TOGGLE[rule.category];
62
+ return toggle ? this.config.rules[toggle] : true;
63
+ });
64
+ this.chainDetector = new chain_detector_1.ChainDetector();
65
+ // Build runtime context
66
+ this.ruleCtx = {
67
+ domainWhitelist: config.domainWhitelist,
68
+ };
69
+ }
70
+ /**
71
+ * Scan a single AuditAction, return 0~N security alerts
72
+ */
73
+ scan(action) {
74
+ if (!this.config.enabled)
75
+ return [];
76
+ this.stats.scanned++;
77
+ const alerts = [];
78
+ // --- L1: Rule quick scan ---
79
+ const text = this.extractText(action);
80
+ for (const rule of this.rules) {
81
+ if (!rule.enabled)
82
+ continue;
83
+ try {
84
+ const findings = rule.detect(text, action, this.ruleCtx);
85
+ for (const f of findings) {
86
+ alerts.push(this.toAlert(f, action));
87
+ }
88
+ }
89
+ catch (err) {
90
+ console.error(`[audit-security] Rule ${rule.id} error:`, err);
91
+ }
92
+ }
93
+ // --- L2: Behavior chain detection ---
94
+ if (this.config.rules.chainDetection) {
95
+ try {
96
+ const chainFindings = this.chainDetector.process(action);
97
+ for (const f of chainFindings) {
98
+ alerts.push(this.toAlert(f, action));
99
+ }
100
+ }
101
+ catch (err) {
102
+ console.error('[audit-security] Chain detector error:', err);
103
+ }
104
+ }
105
+ this.stats.alertsGenerated += alerts.length;
106
+ return alerts;
107
+ }
108
+ /** Get statistics */
109
+ getStats() {
110
+ return { ...this.stats };
111
+ }
112
+ /** Reset */
113
+ reset() {
114
+ this.chainDetector.reset();
115
+ this.stats = { scanned: 0, alertsGenerated: 0 };
116
+ }
117
+ /* ---------------------------------------------------------------- */
118
+ /* Internal methods */
119
+ /* ---------------------------------------------------------------- */
120
+ /** Extract all scannable text from an action */
121
+ extractText(action) {
122
+ const parts = [];
123
+ if (action.inputParams)
124
+ parts.push(JSON.stringify(action.inputParams));
125
+ if (action.outputResult)
126
+ parts.push(JSON.stringify(action.outputResult));
127
+ return parts.join('\n');
128
+ }
129
+ /** SecurityFinding -> SecurityAlert */
130
+ toAlert(finding, action) {
131
+ return {
132
+ alertId: (0, crypto_1.randomUUID)(),
133
+ sessionId: action.sessionId,
134
+ actionType: action.actionType,
135
+ actionName: action.actionName,
136
+ ruleId: finding.ruleId,
137
+ ruleName: finding.ruleName,
138
+ category: finding.category,
139
+ severity: finding.severity,
140
+ finding: finding.finding,
141
+ context: finding.context,
142
+ status: 'open',
143
+ userId: action.userId,
144
+ modelName: action.modelName,
145
+ createdAt: new Date(),
146
+ };
147
+ }
148
+ }
149
+ exports.SecurityScanner = SecurityScanner;
150
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../../src/security/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Security audit type definitions
3
+ */
4
+ /** Security rule severity level */
5
+ export declare enum Severity {
6
+ INFO = "info",
7
+ WARN = "warn",
8
+ CRITICAL = "critical"
9
+ }
10
+ /** Security rule category */
11
+ export declare enum RuleCategory {
12
+ SecretLeakage = "secret_leakage",
13
+ HighRiskOp = "high_risk_operation",
14
+ DataExfil = "data_exfiltration",
15
+ PromptInjection = "prompt_injection",
16
+ SkillAnomaly = "skill_anomaly"
17
+ }
18
+ /** Security alert record */
19
+ export interface SecurityAlert {
20
+ alertId: string;
21
+ sessionId: string;
22
+ actionType: string;
23
+ actionName: string;
24
+ ruleId: string;
25
+ ruleName: string;
26
+ category: RuleCategory;
27
+ severity: Severity;
28
+ /** Finding summary (redacted) */
29
+ finding: string;
30
+ /** Context (match location, surrounding text, etc.) */
31
+ context: string;
32
+ /** Processing status */
33
+ status: 'open' | 'acknowledged' | 'resolved' | 'false_positive';
34
+ userId: string;
35
+ modelName: string;
36
+ createdAt: Date;
37
+ }
38
+ /** Security scan finding (intermediate state, not yet persisted) */
39
+ export interface SecurityFinding {
40
+ ruleId: string;
41
+ ruleName: string;
42
+ category: RuleCategory;
43
+ severity: Severity;
44
+ finding: string;
45
+ context: string;
46
+ }
47
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/security/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,mCAAmC;AACnC,oBAAY,QAAQ;IAClB,IAAI,SAAS;IACb,IAAI,SAAS;IACb,QAAQ,aAAa;CACtB;AAED,6BAA6B;AAC7B,oBAAY,YAAY;IACtB,aAAa,mBAAmB;IAChC,UAAU,wBAAwB;IAClC,SAAS,sBAAsB;IAC/B,eAAe,qBAAqB;IACpC,YAAY,kBAAkB;CAC/B;AAED,4BAA4B;AAC5B,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IAEnB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IAEnB,iCAAiC;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC;IAEhB,wBAAwB;IACxB,MAAM,EAAE,MAAM,GAAG,cAAc,GAAG,UAAU,GAAG,gBAAgB,CAAC;IAEhE,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,IAAI,CAAC;CACjB;AAED,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CACjB"}
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ /**
3
+ * Security audit type definitions
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.RuleCategory = exports.Severity = void 0;
7
+ /** Security rule severity level */
8
+ var Severity;
9
+ (function (Severity) {
10
+ Severity["INFO"] = "info";
11
+ Severity["WARN"] = "warn";
12
+ Severity["CRITICAL"] = "critical";
13
+ })(Severity || (exports.Severity = Severity = {}));
14
+ /** Security rule category */
15
+ var RuleCategory;
16
+ (function (RuleCategory) {
17
+ RuleCategory["SecretLeakage"] = "secret_leakage";
18
+ RuleCategory["HighRiskOp"] = "high_risk_operation";
19
+ RuleCategory["DataExfil"] = "data_exfiltration";
20
+ RuleCategory["PromptInjection"] = "prompt_injection";
21
+ RuleCategory["SkillAnomaly"] = "skill_anomaly";
22
+ })(RuleCategory || (exports.RuleCategory = RuleCategory = {}));
23
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/security/types.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAEH,mCAAmC;AACnC,IAAY,QAIX;AAJD,WAAY,QAAQ;IAClB,yBAAa,CAAA;IACb,yBAAa,CAAA;IACb,iCAAqB,CAAA;AACvB,CAAC,EAJW,QAAQ,wBAAR,QAAQ,QAInB;AAED,6BAA6B;AAC7B,IAAY,YAMX;AAND,WAAY,YAAY;IACtB,gDAAgC,CAAA;IAChC,kDAAkC,CAAA;IAClC,+CAA+B,CAAA;IAC/B,oDAAoC,CAAA;IACpC,8CAA8B,CAAA;AAChC,CAAC,EANW,YAAY,4BAAZ,YAAY,QAMvB"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Async batch buffer queue
3
+ * Dual-trigger flush mechanism based on count threshold + time threshold
4
+ */
5
+ import { AuditAction, AuditSession } from '../types';
6
+ import { BufferConfig } from '../config';
7
+ /** Buffer entry type */
8
+ export type BufferEntry = {
9
+ type: 'action';
10
+ data: AuditAction;
11
+ } | {
12
+ type: 'session';
13
+ data: AuditSession;
14
+ };
15
+ /** Flush callback function type */
16
+ export type FlushCallback = (entries: BufferEntry[]) => Promise<void>;
17
+ /**
18
+ * Async batch buffer
19
+ * - Triggers flush when buffer size reaches batchSize
20
+ * - Auto-flushes every flushIntervalMs milliseconds
21
+ * - Supports manual forced flush (e.g. on session end)
22
+ * - Discards oldest entries when buffer exceeds MAX_BUFFER_SIZE
23
+ */
24
+ export declare class AsyncBatchBuffer {
25
+ private buffer;
26
+ private timer;
27
+ private flushing;
28
+ private flushCallback;
29
+ private config;
30
+ constructor(config: BufferConfig, flushCallback: FlushCallback);
31
+ /**
32
+ * Start periodic flush timer
33
+ */
34
+ start(): void;
35
+ /**
36
+ * Stop periodic flush timer
37
+ */
38
+ stop(): void;
39
+ /**
40
+ * Add audit record to buffer
41
+ */
42
+ add(entry: BufferEntry): Promise<void>;
43
+ /**
44
+ * Add audit action record
45
+ */
46
+ addAction(action: AuditAction): Promise<void>;
47
+ /**
48
+ * Add or update session summary record
49
+ */
50
+ addSession(session: AuditSession): Promise<void>;
51
+ /**
52
+ * Force flush buffer (write all entries to database)
53
+ */
54
+ flush(): Promise<void>;
55
+ /**
56
+ * Get current buffer size
57
+ */
58
+ get size(): number;
59
+ /**
60
+ * Graceful shutdown: stop timer and flush remaining data
61
+ */
62
+ shutdown(): Promise<void>;
63
+ }
64
+ //# sourceMappingURL=buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../../src/storage/buffer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAEzC,wBAAwB;AACxB,MAAM,MAAM,WAAW,GACnB;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GACrC;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,YAAY,CAAA;CAAE,CAAC;AAE5C,mCAAmC;AACnC,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAKtE;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,QAAQ,CAAkB;IAClC,OAAO,CAAC,aAAa,CAAgB;IACrC,OAAO,CAAC,MAAM,CAAe;gBAEjB,MAAM,EAAE,YAAY,EAAE,aAAa,EAAE,aAAa;IAK9D;;OAEG;IACH,KAAK,IAAI,IAAI;IAiBb;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACG,GAAG,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAgB5C;;OAEG;IACG,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAInD;;OAEG;IACG,UAAU,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAuB5B;;OAEG;IACH,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;CAIhC"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ /**
3
+ * Async batch buffer queue
4
+ * Dual-trigger flush mechanism based on count threshold + time threshold
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.AsyncBatchBuffer = void 0;
8
+ /** Max buffer entries (oldest entries are discarded when exceeded) */
9
+ const MAX_BUFFER_SIZE = 5000;
10
+ /**
11
+ * Async batch buffer
12
+ * - Triggers flush when buffer size reaches batchSize
13
+ * - Auto-flushes every flushIntervalMs milliseconds
14
+ * - Supports manual forced flush (e.g. on session end)
15
+ * - Discards oldest entries when buffer exceeds MAX_BUFFER_SIZE
16
+ */
17
+ class AsyncBatchBuffer {
18
+ buffer = [];
19
+ timer = null;
20
+ flushing = false;
21
+ flushCallback;
22
+ config;
23
+ constructor(config, flushCallback) {
24
+ this.config = config;
25
+ this.flushCallback = flushCallback;
26
+ }
27
+ /**
28
+ * Start periodic flush timer
29
+ */
30
+ start() {
31
+ if (this.timer) {
32
+ return;
33
+ }
34
+ this.timer = setInterval(async () => {
35
+ if (this.buffer.length > 0) {
36
+ await this.flush();
37
+ }
38
+ }, this.config.flushIntervalMs);
39
+ // Ensure timer does not prevent process exit
40
+ if (this.timer && typeof this.timer === 'object' && 'unref' in this.timer) {
41
+ this.timer.unref();
42
+ }
43
+ }
44
+ /**
45
+ * Stop periodic flush timer
46
+ */
47
+ stop() {
48
+ if (this.timer) {
49
+ clearInterval(this.timer);
50
+ this.timer = null;
51
+ }
52
+ }
53
+ /**
54
+ * Add audit record to buffer
55
+ */
56
+ async add(entry) {
57
+ // Prevent unbounded buffer growth (when flush keeps failing)
58
+ if (this.buffer.length >= MAX_BUFFER_SIZE) {
59
+ const drop = Math.floor(MAX_BUFFER_SIZE * 0.1); // discard oldest 10%
60
+ this.buffer.splice(0, drop);
61
+ console.warn(`[audit-duckdb] Buffer overflow, dropped ${drop} oldest entries`);
62
+ }
63
+ this.buffer.push(entry);
64
+ // Threshold reached, trigger flush
65
+ if (this.buffer.length >= this.config.batchSize) {
66
+ await this.flush();
67
+ }
68
+ }
69
+ /**
70
+ * Add audit action record
71
+ */
72
+ async addAction(action) {
73
+ await this.add({ type: 'action', data: action });
74
+ }
75
+ /**
76
+ * Add or update session summary record
77
+ */
78
+ async addSession(session) {
79
+ await this.add({ type: 'session', data: session });
80
+ }
81
+ /**
82
+ * Force flush buffer (write all entries to database)
83
+ */
84
+ async flush() {
85
+ // Prevent concurrent flushes
86
+ if (this.flushing || this.buffer.length === 0) {
87
+ return;
88
+ }
89
+ this.flushing = true;
90
+ // Take all current buffer contents
91
+ const entries = [...this.buffer];
92
+ this.buffer = [];
93
+ try {
94
+ await this.flushCallback(entries);
95
+ }
96
+ catch (error) {
97
+ // On flush failure, put entries back (prepend to maintain order)
98
+ this.buffer = [...entries, ...this.buffer];
99
+ console.error('[audit-duckdb] Failed to flush buffer:', error);
100
+ }
101
+ finally {
102
+ this.flushing = false;
103
+ }
104
+ }
105
+ /**
106
+ * Get current buffer size
107
+ */
108
+ get size() {
109
+ return this.buffer.length;
110
+ }
111
+ /**
112
+ * Graceful shutdown: stop timer and flush remaining data
113
+ */
114
+ async shutdown() {
115
+ this.stop();
116
+ await this.flush();
117
+ }
118
+ }
119
+ exports.AsyncBatchBuffer = AsyncBatchBuffer;
120
+ //# sourceMappingURL=buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../../src/storage/buffer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ /**
2
+ * DuckDB local write layer
3
+ * Uses embedded DuckDB (@duckdb/node-api), zero-config out of the box
4
+ */
5
+ import { SecurityAlert } from '../security/types';
6
+ import { BufferEntry } from './buffer';
7
+ import { QueryPool, AuditWriter } from './writer';
8
+ import { DuckDBConfig } from '../config';
9
+ export declare class DuckDBLocalWriter implements AuditWriter {
10
+ private pool;
11
+ private config;
12
+ private initialized;
13
+ private initializing;
14
+ constructor(config: DuckDBConfig);
15
+ initialize(maxRetries?: number, retryDelayMs?: number): Promise<void>;
16
+ ensureReady(): Promise<boolean>;
17
+ private _doInitialize;
18
+ writeBatch(entries: BufferEntry[]): Promise<void>;
19
+ private writeActions;
20
+ private writeSessions;
21
+ writeAlerts(alerts: SecurityAlert[]): Promise<void>;
22
+ getPool(): QueryPool | null;
23
+ close(): Promise<void>;
24
+ private _formatDate;
25
+ }
26
+ //# sourceMappingURL=duckdb-local-writer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duckdb-local-writer.d.ts","sourceRoot":"","sources":["../../src/storage/duckdb-local-writer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAKH,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AA+NzC,qBAAa,iBAAkB,YAAW,WAAW;IACnD,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,MAAM,CAAe;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,YAAY;IAI1B,UAAU,CAAC,UAAU,SAAI,EAAE,YAAY,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAwB9D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;YAUvB,aAAa;IAqCrB,UAAU,CAAC,OAAO,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;YAWzC,YAAY;YAsBZ,aAAa;IAqErB,WAAW,CAAC,MAAM,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoBzD,OAAO,IAAI,SAAS,GAAG,IAAI;IAIrB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAW5B,OAAO,CAAC,WAAW;CAKpB"}