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,115 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit Web API — query database and return structured data
|
|
3
|
+
* Compatible with both MySQL and DuckDB backends
|
|
4
|
+
*/
|
|
5
|
+
import { QueryPool } from '../storage/writer';
|
|
6
|
+
export interface StatsResult {
|
|
7
|
+
totalSessions: number;
|
|
8
|
+
totalActions: number;
|
|
9
|
+
totalTokens: number;
|
|
10
|
+
avgLatencyMs: number;
|
|
11
|
+
successRate: number;
|
|
12
|
+
actionTypeCounts: Record<string, number>;
|
|
13
|
+
}
|
|
14
|
+
export interface SessionRow {
|
|
15
|
+
session_id: string;
|
|
16
|
+
user_id: string;
|
|
17
|
+
model_name: string;
|
|
18
|
+
start_time: string;
|
|
19
|
+
end_time: string | null;
|
|
20
|
+
total_actions: number;
|
|
21
|
+
total_tokens: number;
|
|
22
|
+
}
|
|
23
|
+
export interface ActionRow {
|
|
24
|
+
id: number;
|
|
25
|
+
session_id: string;
|
|
26
|
+
action_type: string;
|
|
27
|
+
action_name: string;
|
|
28
|
+
model_name: string;
|
|
29
|
+
input_params: string | null;
|
|
30
|
+
output_result: string | null;
|
|
31
|
+
prompt_tokens: number | null;
|
|
32
|
+
completion_tokens: number | null;
|
|
33
|
+
duration_ms: number | null;
|
|
34
|
+
user_id: string;
|
|
35
|
+
created_at: string;
|
|
36
|
+
}
|
|
37
|
+
/** Get summary statistics */
|
|
38
|
+
export declare function getStats(pool: QueryPool): Promise<StatsResult>;
|
|
39
|
+
/** Get session list */
|
|
40
|
+
export declare function getSessions(pool: QueryPool, params: {
|
|
41
|
+
page?: number;
|
|
42
|
+
limit?: number;
|
|
43
|
+
userId?: string;
|
|
44
|
+
model?: string;
|
|
45
|
+
sessionId?: string;
|
|
46
|
+
search?: string;
|
|
47
|
+
timeFrom?: string;
|
|
48
|
+
timeTo?: string;
|
|
49
|
+
}): Promise<{
|
|
50
|
+
sessions: SessionRow[];
|
|
51
|
+
total: number;
|
|
52
|
+
}>;
|
|
53
|
+
/** Get actions for a session (supports field selection and limit) */
|
|
54
|
+
export declare function getSessionActions(pool: QueryPool, sessionId: string, options?: {
|
|
55
|
+
fields?: string;
|
|
56
|
+
limit?: number;
|
|
57
|
+
}): Promise<ActionRow[]>;
|
|
58
|
+
/** Get action list */
|
|
59
|
+
export declare function getActions(pool: QueryPool, params: {
|
|
60
|
+
page?: number;
|
|
61
|
+
limit?: number;
|
|
62
|
+
actionType?: string;
|
|
63
|
+
sessionId?: string;
|
|
64
|
+
}): Promise<{
|
|
65
|
+
actions: ActionRow[];
|
|
66
|
+
total: number;
|
|
67
|
+
}>;
|
|
68
|
+
export interface AlertRow {
|
|
69
|
+
id: number;
|
|
70
|
+
alert_id: string;
|
|
71
|
+
session_id: string;
|
|
72
|
+
action_type: string;
|
|
73
|
+
action_name: string;
|
|
74
|
+
rule_id: string;
|
|
75
|
+
rule_name: string;
|
|
76
|
+
category: string;
|
|
77
|
+
severity: string;
|
|
78
|
+
finding: string;
|
|
79
|
+
context: string;
|
|
80
|
+
status: string;
|
|
81
|
+
resolved_by: string | null;
|
|
82
|
+
resolved_at: string | null;
|
|
83
|
+
user_id: string;
|
|
84
|
+
model_name: string;
|
|
85
|
+
created_at: string;
|
|
86
|
+
}
|
|
87
|
+
/** Get security alert list */
|
|
88
|
+
export declare function getAlerts(pool: QueryPool, params: {
|
|
89
|
+
page?: number;
|
|
90
|
+
limit?: number;
|
|
91
|
+
severity?: string;
|
|
92
|
+
category?: string;
|
|
93
|
+
status?: string;
|
|
94
|
+
sessionId?: string;
|
|
95
|
+
ruleId?: string;
|
|
96
|
+
search?: string;
|
|
97
|
+
timeFrom?: string;
|
|
98
|
+
timeTo?: string;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
alerts: AlertRow[];
|
|
101
|
+
total: number;
|
|
102
|
+
}>;
|
|
103
|
+
/** Get security alert statistics */
|
|
104
|
+
export declare function getAlertStats(pool: QueryPool): Promise<{
|
|
105
|
+
total: number;
|
|
106
|
+
bySeverity: Record<string, number>;
|
|
107
|
+
byCategory: Record<string, number>;
|
|
108
|
+
byStatus: Record<string, number>;
|
|
109
|
+
recent24h: number;
|
|
110
|
+
}>;
|
|
111
|
+
/** Update alert status */
|
|
112
|
+
export declare function updateAlertStatus(pool: QueryPool, alertId: string, status: string, resolvedBy?: string): Promise<boolean>;
|
|
113
|
+
/** Get alerts for a session */
|
|
114
|
+
export declare function getSessionAlerts(pool: QueryPool, sessionId: string): Promise<AlertRow[]>;
|
|
115
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/web/api.ts"],"names":[],"mappings":"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"}
|
package/dist/web/api.js
ADDED
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audit Web API — query database and return structured data
|
|
4
|
+
* Compatible with both MySQL and DuckDB backends
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.getStats = getStats;
|
|
8
|
+
exports.getSessions = getSessions;
|
|
9
|
+
exports.getSessionActions = getSessionActions;
|
|
10
|
+
exports.getActions = getActions;
|
|
11
|
+
exports.getAlerts = getAlerts;
|
|
12
|
+
exports.getAlertStats = getAlertStats;
|
|
13
|
+
exports.updateAlertStatus = updateAlertStatus;
|
|
14
|
+
exports.getSessionAlerts = getSessionAlerts;
|
|
15
|
+
/* ------------------------------------------------------------------ */
|
|
16
|
+
/* API functions */
|
|
17
|
+
/* ------------------------------------------------------------------ */
|
|
18
|
+
/** Get summary statistics */
|
|
19
|
+
async function getStats(pool) {
|
|
20
|
+
const [sessionRows] = await pool.query('SELECT COUNT(*) as cnt FROM audit_sessions');
|
|
21
|
+
const [actionRows] = await pool.query(`SELECT COUNT(*) as cnt,
|
|
22
|
+
COALESCE(SUM(COALESCE(prompt_tokens,0) + COALESCE(completion_tokens,0)), 0) as tokens,
|
|
23
|
+
COALESCE(AVG(NULLIF(duration_ms, 0)), 0) as avg_latency
|
|
24
|
+
FROM audit_actions`);
|
|
25
|
+
const [successRows] = await pool.query(`SELECT COUNT(*) as cnt FROM audit_actions
|
|
26
|
+
WHERE action_type = 'agent_end' AND output_result LIKE '%"success":true%'`);
|
|
27
|
+
const [totalEndRows] = await pool.query(`SELECT COUNT(*) as cnt FROM audit_actions WHERE action_type = 'agent_end'`);
|
|
28
|
+
// Count by action_type
|
|
29
|
+
const [typeCounts] = await pool.query('SELECT action_type, COUNT(*) as cnt FROM audit_actions GROUP BY action_type ORDER BY cnt DESC');
|
|
30
|
+
const actionTypeCounts = {};
|
|
31
|
+
for (const row of typeCounts) {
|
|
32
|
+
actionTypeCounts[row.action_type] = Number(row.cnt);
|
|
33
|
+
}
|
|
34
|
+
const totalEnd = Number(totalEndRows[0]?.cnt ?? 0);
|
|
35
|
+
return {
|
|
36
|
+
totalSessions: Number(sessionRows[0]?.cnt ?? 0),
|
|
37
|
+
totalActions: Number(actionRows[0]?.cnt ?? 0),
|
|
38
|
+
totalTokens: Number(actionRows[0]?.tokens ?? 0),
|
|
39
|
+
avgLatencyMs: Math.round(Number(actionRows[0]?.avg_latency ?? 0)),
|
|
40
|
+
successRate: totalEnd > 0
|
|
41
|
+
? Math.round(Number(successRows[0]?.cnt ?? 0) / totalEnd * 100)
|
|
42
|
+
: 100,
|
|
43
|
+
actionTypeCounts,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
/** Get session list */
|
|
47
|
+
async function getSessions(pool, params) {
|
|
48
|
+
const page = params.page || 1;
|
|
49
|
+
const limit = Math.min(params.limit || 20, 100);
|
|
50
|
+
const offset = (page - 1) * limit;
|
|
51
|
+
let where = '1=1';
|
|
52
|
+
const values = [];
|
|
53
|
+
if (params.sessionId) {
|
|
54
|
+
where += ' AND session_id = ?';
|
|
55
|
+
values.push(params.sessionId);
|
|
56
|
+
}
|
|
57
|
+
if (params.userId) {
|
|
58
|
+
where += ' AND user_id = ?';
|
|
59
|
+
values.push(params.userId);
|
|
60
|
+
}
|
|
61
|
+
if (params.model) {
|
|
62
|
+
where += ' AND model_name LIKE ?';
|
|
63
|
+
values.push('%' + params.model + '%');
|
|
64
|
+
}
|
|
65
|
+
// Full-text search: search session metadata first, then action content (input_params / output_result)
|
|
66
|
+
if (params.search) {
|
|
67
|
+
const like = '%' + params.search + '%';
|
|
68
|
+
where += ` AND (
|
|
69
|
+
session_id LIKE ? OR user_id LIKE ? OR model_name LIKE ?
|
|
70
|
+
OR session_id IN (
|
|
71
|
+
SELECT DISTINCT session_id FROM audit_actions
|
|
72
|
+
WHERE input_params LIKE ? OR output_result LIKE ? OR action_name LIKE ?
|
|
73
|
+
)
|
|
74
|
+
)`;
|
|
75
|
+
values.push(like, like, like, like, like, like);
|
|
76
|
+
}
|
|
77
|
+
// Time range filter
|
|
78
|
+
if (params.timeFrom) {
|
|
79
|
+
where += ' AND start_time >= ?';
|
|
80
|
+
values.push(params.timeFrom);
|
|
81
|
+
}
|
|
82
|
+
if (params.timeTo) {
|
|
83
|
+
where += ' AND start_time <= ?';
|
|
84
|
+
values.push(params.timeTo);
|
|
85
|
+
}
|
|
86
|
+
const [countRows] = await pool.query('SELECT COUNT(*) as cnt FROM audit_sessions WHERE ' + where, values);
|
|
87
|
+
const [rows] = await pool.query('SELECT * FROM audit_sessions WHERE ' + where + ' ORDER BY start_time DESC LIMIT ? OFFSET ?', [...values, limit, offset]);
|
|
88
|
+
return {
|
|
89
|
+
sessions: rows,
|
|
90
|
+
total: Number(countRows[0]?.cnt ?? 0),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Get actions for a session (supports field selection and limit) */
|
|
94
|
+
async function getSessionActions(pool, sessionId, options) {
|
|
95
|
+
// If fields=action_type, return only minimal fields (for mini trace)
|
|
96
|
+
const selectCols = options?.fields === 'action_type'
|
|
97
|
+
? 'action_type, created_at'
|
|
98
|
+
: '*';
|
|
99
|
+
const limitClause = options?.limit ? ` LIMIT ${Math.min(options.limit, 1000)}` : '';
|
|
100
|
+
const [rows] = await pool.query(`SELECT ${selectCols} FROM audit_actions WHERE session_id = ? ORDER BY created_at ASC, id ASC${limitClause}`, [sessionId]);
|
|
101
|
+
return rows;
|
|
102
|
+
}
|
|
103
|
+
/** Get action list */
|
|
104
|
+
async function getActions(pool, params) {
|
|
105
|
+
const page = params.page || 1;
|
|
106
|
+
const limit = Math.min(params.limit || 50, 200);
|
|
107
|
+
const offset = (page - 1) * limit;
|
|
108
|
+
let where = '1=1';
|
|
109
|
+
const values = [];
|
|
110
|
+
if (params.actionType) {
|
|
111
|
+
where += ' AND action_type = ?';
|
|
112
|
+
values.push(params.actionType);
|
|
113
|
+
}
|
|
114
|
+
if (params.sessionId) {
|
|
115
|
+
where += ' AND session_id = ?';
|
|
116
|
+
values.push(params.sessionId);
|
|
117
|
+
}
|
|
118
|
+
const [countRows] = await pool.query('SELECT COUNT(*) as cnt FROM audit_actions WHERE ' + where, values);
|
|
119
|
+
const [rows] = await pool.query('SELECT * FROM audit_actions WHERE ' + where + ' ORDER BY created_at DESC, id DESC LIMIT ? OFFSET ?', [...values, limit, offset]);
|
|
120
|
+
return {
|
|
121
|
+
actions: rows,
|
|
122
|
+
total: Number(countRows[0]?.cnt ?? 0),
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/** Get security alert list */
|
|
126
|
+
async function getAlerts(pool, params) {
|
|
127
|
+
const page = params.page || 1;
|
|
128
|
+
const limit = Math.min(params.limit || 20, 100);
|
|
129
|
+
const offset = (page - 1) * limit;
|
|
130
|
+
let where = '1=1';
|
|
131
|
+
const values = [];
|
|
132
|
+
if (params.severity) {
|
|
133
|
+
where += ' AND severity = ?';
|
|
134
|
+
values.push(params.severity);
|
|
135
|
+
}
|
|
136
|
+
if (params.category) {
|
|
137
|
+
where += ' AND category = ?';
|
|
138
|
+
values.push(params.category);
|
|
139
|
+
}
|
|
140
|
+
if (params.status) {
|
|
141
|
+
where += ' AND status = ?';
|
|
142
|
+
values.push(params.status);
|
|
143
|
+
}
|
|
144
|
+
if (params.sessionId) {
|
|
145
|
+
where += ' AND session_id = ?';
|
|
146
|
+
values.push(params.sessionId);
|
|
147
|
+
}
|
|
148
|
+
if (params.ruleId) {
|
|
149
|
+
where += ' AND rule_id = ?';
|
|
150
|
+
values.push(params.ruleId);
|
|
151
|
+
}
|
|
152
|
+
// Full-text search across alert fields
|
|
153
|
+
if (params.search) {
|
|
154
|
+
const like = '%' + params.search + '%';
|
|
155
|
+
where += ` AND (
|
|
156
|
+
rule_name LIKE ? OR rule_id LIKE ? OR finding LIKE ?
|
|
157
|
+
OR session_id LIKE ? OR action_name LIKE ? OR context LIKE ?
|
|
158
|
+
)`;
|
|
159
|
+
values.push(like, like, like, like, like, like);
|
|
160
|
+
}
|
|
161
|
+
if (params.timeFrom) {
|
|
162
|
+
where += ' AND created_at >= ?';
|
|
163
|
+
values.push(params.timeFrom);
|
|
164
|
+
}
|
|
165
|
+
if (params.timeTo) {
|
|
166
|
+
where += ' AND created_at <= ?';
|
|
167
|
+
values.push(params.timeTo);
|
|
168
|
+
}
|
|
169
|
+
const [countRows] = await pool.query('SELECT COUNT(*) as cnt FROM audit_alerts WHERE ' + where, values);
|
|
170
|
+
const [rows] = await pool.query('SELECT * FROM audit_alerts WHERE ' + where + ' ORDER BY created_at DESC LIMIT ? OFFSET ?', [...values, limit, offset]);
|
|
171
|
+
return {
|
|
172
|
+
alerts: rows,
|
|
173
|
+
total: Number(countRows[0]?.cnt ?? 0),
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
/** Get security alert statistics */
|
|
177
|
+
async function getAlertStats(pool) {
|
|
178
|
+
const [totalRows] = await pool.query('SELECT COUNT(*) as cnt FROM audit_alerts');
|
|
179
|
+
const [sevRows] = await pool.query('SELECT severity, COUNT(*) as cnt FROM audit_alerts GROUP BY severity');
|
|
180
|
+
const [catRows] = await pool.query('SELECT category, COUNT(*) as cnt FROM audit_alerts GROUP BY category');
|
|
181
|
+
const [statusRows] = await pool.query('SELECT status, COUNT(*) as cnt FROM audit_alerts GROUP BY status');
|
|
182
|
+
// NOW() - INTERVAL 24 HOUR compatible with MySQL and DuckDB
|
|
183
|
+
const [recentRows] = await pool.query('SELECT COUNT(*) as cnt FROM audit_alerts WHERE created_at >= (NOW() - INTERVAL 24 HOUR)');
|
|
184
|
+
const bySeverity = {};
|
|
185
|
+
for (const r of sevRows)
|
|
186
|
+
bySeverity[r.severity] = Number(r.cnt);
|
|
187
|
+
const byCategory = {};
|
|
188
|
+
for (const r of catRows)
|
|
189
|
+
byCategory[r.category] = Number(r.cnt);
|
|
190
|
+
const byStatus = {};
|
|
191
|
+
for (const r of statusRows)
|
|
192
|
+
byStatus[r.status] = Number(r.cnt);
|
|
193
|
+
return {
|
|
194
|
+
total: Number(totalRows[0]?.cnt ?? 0),
|
|
195
|
+
bySeverity,
|
|
196
|
+
byCategory,
|
|
197
|
+
byStatus,
|
|
198
|
+
recent24h: Number(recentRows[0]?.cnt ?? 0),
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/** Update alert status */
|
|
202
|
+
async function updateAlertStatus(pool, alertId, status, resolvedBy) {
|
|
203
|
+
const validStatuses = ['open', 'acknowledged', 'resolved', 'false_positive'];
|
|
204
|
+
if (!validStatuses.includes(status))
|
|
205
|
+
return false;
|
|
206
|
+
const resolvedAt = (status === 'resolved' || status === 'false_positive')
|
|
207
|
+
? new Date().toISOString().replace('T', ' ').slice(0, 19) // compatible with MySQL & DuckDB
|
|
208
|
+
: null;
|
|
209
|
+
await pool.query(`UPDATE audit_alerts SET status = ?, resolved_by = ?, resolved_at = ? WHERE alert_id = ?`, [status, resolvedBy || null, resolvedAt, alertId]);
|
|
210
|
+
// Verify update result (compatible with MySQL and DuckDB, not relying on affectedRows)
|
|
211
|
+
const [rows] = await pool.query('SELECT 1 FROM audit_alerts WHERE alert_id = ? AND status = ?', [alertId, status]);
|
|
212
|
+
return rows.length > 0;
|
|
213
|
+
}
|
|
214
|
+
/** Get alerts for a session */
|
|
215
|
+
async function getSessionAlerts(pool, sessionId) {
|
|
216
|
+
const [rows] = await pool.query('SELECT * FROM audit_alerts WHERE session_id = ? ORDER BY created_at ASC', [sessionId]);
|
|
217
|
+
return rows;
|
|
218
|
+
}
|
|
219
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/web/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit panel HTTP route registration
|
|
3
|
+
* Mounts API and UI pages on the OpenClaw Gateway
|
|
4
|
+
*/
|
|
5
|
+
import { IncomingMessage, ServerResponse } from 'node:http';
|
|
6
|
+
import { AuditWriter } from '../storage/writer';
|
|
7
|
+
export interface RegisterHttpRoute {
|
|
8
|
+
(params: {
|
|
9
|
+
path: string;
|
|
10
|
+
handler: (req: IncomingMessage, res: ServerResponse) => Promise<boolean | void> | boolean | void;
|
|
11
|
+
auth: 'gateway' | 'plugin';
|
|
12
|
+
match?: 'exact' | 'prefix';
|
|
13
|
+
replaceExisting?: boolean;
|
|
14
|
+
}): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Register all audit panel HTTP routes
|
|
18
|
+
*/
|
|
19
|
+
export declare function registerAuditRoutes(registerHttpRoute: RegisterHttpRoute, writer: AuditWriter): void;
|
|
20
|
+
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.d.ts","sourceRoot":"","sources":["../../src/web/routes.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAG5D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAMhD,MAAM,WAAW,iBAAiB;IAChC,CAAC,MAAM,EAAE;QACP,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,CAAC,GAAG,EAAE,eAAe,EAAE,GAAG,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC;QACjG,IAAI,EAAE,SAAS,GAAG,QAAQ,CAAC;QAC3B,KAAK,CAAC,EAAE,OAAO,GAAG,QAAQ,CAAC;QAC3B,eAAe,CAAC,EAAE,OAAO,CAAC;KAC3B,GAAG,IAAI,CAAC;CACV;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CACjC,iBAAiB,EAAE,iBAAiB,EACpC,MAAM,EAAE,WAAW,GAClB,IAAI,CAuIN"}
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Audit panel HTTP route registration
|
|
4
|
+
* Mounts API and UI pages on the OpenClaw Gateway
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.registerAuditRoutes = registerAuditRoutes;
|
|
8
|
+
const api_1 = require("./api");
|
|
9
|
+
const ui_1 = require("./ui");
|
|
10
|
+
/**
|
|
11
|
+
* Register all audit panel HTTP routes
|
|
12
|
+
*/
|
|
13
|
+
function registerAuditRoutes(registerHttpRoute, writer) {
|
|
14
|
+
// Single prefix route handles all requests
|
|
15
|
+
registerHttpRoute({
|
|
16
|
+
path: '/plugins/audit',
|
|
17
|
+
handler: async (req, res) => {
|
|
18
|
+
try {
|
|
19
|
+
const url = parseUrl(req);
|
|
20
|
+
const path = url.pathname;
|
|
21
|
+
// Non-API paths return UI HTML directly (no database needed)
|
|
22
|
+
if (!path.startsWith('/plugins/audit/api/')) {
|
|
23
|
+
sendHtml(res, (0, ui_1.getAppHtml)());
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
// API paths require database, attempt lazy initialization
|
|
27
|
+
await writer.ensureReady();
|
|
28
|
+
const pool = writer.getPool();
|
|
29
|
+
if (!pool) {
|
|
30
|
+
sendJson(res, 503, { error: 'Database not ready — will retry automatically' });
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// ---------- API routes ----------
|
|
34
|
+
// GET /plugins/audit/api/stats
|
|
35
|
+
if (path === '/plugins/audit/api/stats') {
|
|
36
|
+
const stats = await (0, api_1.getStats)(pool);
|
|
37
|
+
sendJson(res, 200, stats);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
// GET /plugins/audit/api/sessions
|
|
41
|
+
if (path === '/plugins/audit/api/sessions') {
|
|
42
|
+
const page = intParam(url, 'page', 1);
|
|
43
|
+
const limit = intParam(url, 'limit', 20);
|
|
44
|
+
const userId = url.searchParams.get('user_id') || undefined;
|
|
45
|
+
const model = url.searchParams.get('model') || undefined;
|
|
46
|
+
const sessionId = url.searchParams.get('sessionId') || undefined;
|
|
47
|
+
const search = url.searchParams.get('search') || undefined;
|
|
48
|
+
const timeFrom = url.searchParams.get('timeFrom') || undefined;
|
|
49
|
+
const timeTo = url.searchParams.get('timeTo') || undefined;
|
|
50
|
+
const result = await (0, api_1.getSessions)(pool, { page, limit, userId, model, sessionId, search, timeFrom, timeTo });
|
|
51
|
+
sendJson(res, 200, result);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
// GET /plugins/audit/api/sessions/:id/actions
|
|
55
|
+
const sessionActionsMatch = path.match(/^\/plugins\/audit\/api\/sessions\/([^/]+)\/actions$/);
|
|
56
|
+
if (sessionActionsMatch) {
|
|
57
|
+
const sessionId = decodeURIComponent(sessionActionsMatch[1]);
|
|
58
|
+
const fields = url.searchParams.get('fields') || undefined;
|
|
59
|
+
const limitParam = url.searchParams.get('limit');
|
|
60
|
+
const limit = limitParam ? parseInt(limitParam, 10) : undefined;
|
|
61
|
+
const actions = await (0, api_1.getSessionActions)(pool, sessionId, { fields, limit });
|
|
62
|
+
sendJson(res, 200, { actions });
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// GET /plugins/audit/api/actions
|
|
66
|
+
if (path === '/plugins/audit/api/actions') {
|
|
67
|
+
const page = intParam(url, 'page', 1);
|
|
68
|
+
const limit = intParam(url, 'limit', 50);
|
|
69
|
+
const actionType = url.searchParams.get('action_type') || undefined;
|
|
70
|
+
const sessionId = url.searchParams.get('session_id') || undefined;
|
|
71
|
+
const result = await (0, api_1.getActions)(pool, { page, limit, actionType, sessionId });
|
|
72
|
+
sendJson(res, 200, result);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// ---------- Security Alert API routes ----------
|
|
76
|
+
// GET /plugins/audit/api/alerts/stats
|
|
77
|
+
if (path === '/plugins/audit/api/alerts/stats') {
|
|
78
|
+
const stats = await (0, api_1.getAlertStats)(pool);
|
|
79
|
+
sendJson(res, 200, stats);
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
// GET /plugins/audit/api/alerts
|
|
83
|
+
if (path === '/plugins/audit/api/alerts') {
|
|
84
|
+
const page = intParam(url, 'page', 1);
|
|
85
|
+
const limit = intParam(url, 'limit', 20);
|
|
86
|
+
const severity = url.searchParams.get('severity') || undefined;
|
|
87
|
+
const category = url.searchParams.get('category') || undefined;
|
|
88
|
+
const status = url.searchParams.get('status') || undefined;
|
|
89
|
+
const sessionId = url.searchParams.get('session_id') || undefined;
|
|
90
|
+
const ruleId = url.searchParams.get('rule_id') || undefined;
|
|
91
|
+
const search = url.searchParams.get('search') || undefined;
|
|
92
|
+
const timeFrom = url.searchParams.get('timeFrom') || undefined;
|
|
93
|
+
const timeTo = url.searchParams.get('timeTo') || undefined;
|
|
94
|
+
const result = await (0, api_1.getAlerts)(pool, { page, limit, severity, category, status, sessionId, ruleId, search, timeFrom, timeTo });
|
|
95
|
+
sendJson(res, 200, result);
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
// POST /plugins/audit/api/alerts/:id/status
|
|
99
|
+
const alertStatusMatch = path.match(/^\/plugins\/audit\/api\/alerts\/([^/]+)\/status$/);
|
|
100
|
+
if (alertStatusMatch && req.method === 'POST') {
|
|
101
|
+
const alertId = decodeURIComponent(alertStatusMatch[1]);
|
|
102
|
+
// Read POST body
|
|
103
|
+
const body = await readBody(req);
|
|
104
|
+
const { status: newStatus, resolvedBy } = JSON.parse(body);
|
|
105
|
+
const ok = await (0, api_1.updateAlertStatus)(pool, alertId, newStatus, resolvedBy);
|
|
106
|
+
sendJson(res, ok ? 200 : 404, { success: ok });
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// GET /plugins/audit/api/sessions/:id/alerts
|
|
110
|
+
const sessionAlertsMatch = path.match(/^\/plugins\/audit\/api\/sessions\/([^/]+)\/alerts$/);
|
|
111
|
+
if (sessionAlertsMatch) {
|
|
112
|
+
const sessionId = decodeURIComponent(sessionAlertsMatch[1]);
|
|
113
|
+
const alerts = await (0, api_1.getSessionAlerts)(pool, sessionId);
|
|
114
|
+
sendJson(res, 200, { alerts });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
// No matching API route
|
|
118
|
+
sendJson(res, 404, { error: 'Not found' });
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
console.error('[audit-duckdb] HTTP handler error:', err);
|
|
122
|
+
sendJson(res, 500, { error: String(err) });
|
|
123
|
+
}
|
|
124
|
+
},
|
|
125
|
+
auth: 'plugin',
|
|
126
|
+
match: 'prefix',
|
|
127
|
+
});
|
|
128
|
+
console.log('[audit-duckdb] Audit UI registered at /plugins/audit/');
|
|
129
|
+
}
|
|
130
|
+
/* ------------------------------------------------------------------ */
|
|
131
|
+
/* Helpers */
|
|
132
|
+
/* ------------------------------------------------------------------ */
|
|
133
|
+
function parseUrl(req) {
|
|
134
|
+
return new URL(req.url || '/', 'http://' + (req.headers.host || 'localhost'));
|
|
135
|
+
}
|
|
136
|
+
function intParam(url, name, defaultVal) {
|
|
137
|
+
const v = url.searchParams.get(name);
|
|
138
|
+
if (!v)
|
|
139
|
+
return defaultVal;
|
|
140
|
+
const n = parseInt(v, 10);
|
|
141
|
+
return isNaN(n) ? defaultVal : n;
|
|
142
|
+
}
|
|
143
|
+
function sendJson(res, status, data) {
|
|
144
|
+
res.writeHead(status, {
|
|
145
|
+
'Content-Type': 'application/json; charset=utf-8',
|
|
146
|
+
'Cache-Control': 'no-cache',
|
|
147
|
+
});
|
|
148
|
+
res.end(JSON.stringify(data));
|
|
149
|
+
}
|
|
150
|
+
function sendHtml(res, html) {
|
|
151
|
+
res.writeHead(200, {
|
|
152
|
+
'Content-Type': 'text/html; charset=utf-8',
|
|
153
|
+
'Cache-Control': 'no-cache',
|
|
154
|
+
});
|
|
155
|
+
res.end(html);
|
|
156
|
+
}
|
|
157
|
+
/** Read request body with max size limit to prevent DoS */
|
|
158
|
+
function readBody(req, maxBytes = 1024 * 64 /* 64KB */) {
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
let data = '';
|
|
161
|
+
let bytes = 0;
|
|
162
|
+
req.on('data', (chunk) => {
|
|
163
|
+
bytes += chunk.length;
|
|
164
|
+
if (bytes > maxBytes) {
|
|
165
|
+
req.destroy();
|
|
166
|
+
reject(new Error(`Request body too large (max ${maxBytes} bytes)`));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
data += chunk.toString();
|
|
170
|
+
});
|
|
171
|
+
req.on('end', () => resolve(data));
|
|
172
|
+
req.on('error', reject);
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=routes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"routes.js","sourceRoot":"","sources":["../../src/web/routes.ts"],"names":[],"mappings":"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"}
|
package/dist/web/ui.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Audit panel SPA — single-page HTML application
|
|
3
|
+
* Contains Dashboard overview + Session Trace detail views
|
|
4
|
+
* Uses hash routing: #/ = Dashboard, #/trace/{sessionId} = Trace
|
|
5
|
+
*
|
|
6
|
+
* Fully aligned with OpenClaw Control design system (CSS variables + dark/light themes)
|
|
7
|
+
*/
|
|
8
|
+
export declare function getAppHtml(): string;
|
|
9
|
+
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/web/ui.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,wBAAgB,UAAU,IAAI,MAAM,CAmBnC"}
|