@waiaas/daemon 2.9.1-rc → 2.10.0-rc
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/api/middleware/master-auth.d.ts +3 -0
- package/dist/api/middleware/master-auth.d.ts.map +1 -1
- package/dist/api/middleware/master-auth.js +14 -0
- package/dist/api/middleware/master-auth.js.map +1 -1
- package/dist/api/routes/admin.d.ts +4 -0
- package/dist/api/routes/admin.d.ts.map +1 -1
- package/dist/api/routes/admin.js +186 -1
- package/dist/api/routes/admin.js.map +1 -1
- package/dist/api/routes/audit-logs.d.ts +15 -0
- package/dist/api/routes/audit-logs.d.ts.map +1 -0
- package/dist/api/routes/audit-logs.js +119 -0
- package/dist/api/routes/audit-logs.js.map +1 -0
- package/dist/api/routes/index.d.ts +2 -1
- package/dist/api/routes/index.d.ts.map +1 -1
- package/dist/api/routes/index.js +2 -1
- package/dist/api/routes/index.js.map +1 -1
- package/dist/api/routes/openapi-schemas.d.ts +324 -6
- package/dist/api/routes/openapi-schemas.d.ts.map +1 -1
- package/dist/api/routes/openapi-schemas.js +76 -0
- package/dist/api/routes/openapi-schemas.js.map +1 -1
- package/dist/api/routes/sessions.d.ts +2 -0
- package/dist/api/routes/sessions.d.ts.map +1 -1
- package/dist/api/routes/sessions.js +21 -0
- package/dist/api/routes/sessions.js.map +1 -1
- package/dist/api/routes/transactions.d.ts +2 -1
- package/dist/api/routes/transactions.d.ts.map +1 -1
- package/dist/api/routes/transactions.js +72 -1
- package/dist/api/routes/transactions.js.map +1 -1
- package/dist/api/routes/wallets.d.ts.map +1 -1
- package/dist/api/routes/wallets.js +25 -0
- package/dist/api/routes/wallets.js.map +1 -1
- package/dist/api/routes/webhooks.d.ts +17 -0
- package/dist/api/routes/webhooks.d.ts.map +1 -0
- package/dist/api/routes/webhooks.js +218 -0
- package/dist/api/routes/webhooks.js.map +1 -0
- package/dist/api/server.d.ts +27 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +31 -5
- package/dist/api/server.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/backup/backup-format.d.ts +107 -0
- package/dist/infrastructure/backup/backup-format.d.ts.map +1 -0
- package/dist/infrastructure/backup/backup-format.js +134 -0
- package/dist/infrastructure/backup/backup-format.js.map +1 -0
- package/dist/infrastructure/backup/encrypted-backup-service.d.ts +56 -0
- package/dist/infrastructure/backup/encrypted-backup-service.d.ts.map +1 -0
- package/dist/infrastructure/backup/encrypted-backup-service.js +269 -0
- package/dist/infrastructure/backup/encrypted-backup-service.js.map +1 -0
- package/dist/infrastructure/backup/index.d.ts +3 -0
- package/dist/infrastructure/backup/index.d.ts.map +1 -1
- package/dist/infrastructure/backup/index.js +2 -0
- package/dist/infrastructure/backup/index.js.map +1 -1
- package/dist/infrastructure/config/loader.d.ts +23 -0
- package/dist/infrastructure/config/loader.d.ts.map +1 -1
- package/dist/infrastructure/config/loader.js +8 -0
- package/dist/infrastructure/config/loader.js.map +1 -1
- package/dist/infrastructure/database/audit-helper.d.ts +29 -0
- package/dist/infrastructure/database/audit-helper.d.ts.map +1 -0
- package/dist/infrastructure/database/audit-helper.js +30 -0
- package/dist/infrastructure/database/audit-helper.js.map +1 -0
- package/dist/infrastructure/database/index.d.ts +2 -0
- package/dist/infrastructure/database/index.d.ts.map +1 -1
- package/dist/infrastructure/database/index.js +1 -0
- package/dist/infrastructure/database/index.js.map +1 -1
- package/dist/infrastructure/database/migrate.d.ts +1 -1
- package/dist/infrastructure/database/migrate.d.ts.map +1 -1
- package/dist/infrastructure/database/migrate.js +83 -2
- package/dist/infrastructure/database/migrate.js.map +1 -1
- package/dist/infrastructure/database/schema.d.ts +343 -1
- package/dist/infrastructure/database/schema.d.ts.map +1 -1
- package/dist/infrastructure/database/schema.js +41 -1
- package/dist/infrastructure/database/schema.js.map +1 -1
- package/dist/infrastructure/metrics/in-memory-counter.d.ts +34 -0
- package/dist/infrastructure/metrics/in-memory-counter.d.ts.map +1 -0
- package/dist/infrastructure/metrics/in-memory-counter.js +88 -0
- package/dist/infrastructure/metrics/in-memory-counter.js.map +1 -0
- package/dist/infrastructure/settings/hot-reload.d.ts +1 -0
- package/dist/infrastructure/settings/hot-reload.d.ts.map +1 -1
- package/dist/infrastructure/settings/hot-reload.js +23 -2
- package/dist/infrastructure/settings/hot-reload.js.map +1 -1
- package/dist/infrastructure/settings/setting-keys.d.ts.map +1 -1
- package/dist/infrastructure/settings/setting-keys.js +4 -0
- package/dist/infrastructure/settings/setting-keys.js.map +1 -1
- package/dist/infrastructure/telegram/telegram-bot-service.d.ts.map +1 -1
- package/dist/infrastructure/telegram/telegram-bot-service.js +32 -19
- package/dist/infrastructure/telegram/telegram-bot-service.js.map +1 -1
- package/dist/lifecycle/daemon.d.ts +8 -1
- package/dist/lifecycle/daemon.d.ts.map +1 -1
- package/dist/lifecycle/daemon.js +103 -1
- package/dist/lifecycle/daemon.js.map +1 -1
- package/dist/pipeline/dry-run.d.ts +68 -0
- package/dist/pipeline/dry-run.d.ts.map +1 -0
- package/dist/pipeline/dry-run.js +426 -0
- package/dist/pipeline/dry-run.js.map +1 -0
- package/dist/pipeline/index.d.ts +1 -0
- package/dist/pipeline/index.d.ts.map +1 -1
- package/dist/pipeline/index.js +2 -0
- package/dist/pipeline/index.js.map +1 -1
- package/dist/pipeline/pipeline.d.ts +18 -1
- package/dist/pipeline/pipeline.d.ts.map +1 -1
- package/dist/pipeline/pipeline.js +38 -0
- package/dist/pipeline/pipeline.js.map +1 -1
- package/dist/pipeline/stages.d.ts +31 -1
- package/dist/pipeline/stages.d.ts.map +1 -1
- package/dist/pipeline/stages.js +120 -22
- package/dist/pipeline/stages.js.map +1 -1
- package/dist/services/admin-stats-service.d.ts +48 -0
- package/dist/services/admin-stats-service.d.ts.map +1 -0
- package/dist/services/admin-stats-service.js +182 -0
- package/dist/services/admin-stats-service.js.map +1 -0
- package/dist/services/autostop/autostop-service.d.ts +83 -0
- package/dist/services/autostop/autostop-service.d.ts.map +1 -0
- package/dist/services/autostop/autostop-service.js +252 -0
- package/dist/services/autostop/autostop-service.js.map +1 -0
- package/dist/services/autostop/index.d.ts +15 -0
- package/dist/services/autostop/index.d.ts.map +1 -0
- package/dist/services/autostop/index.js +11 -0
- package/dist/services/autostop/index.js.map +1 -0
- package/dist/services/autostop/rule-registry.d.ts +42 -0
- package/dist/services/autostop/rule-registry.d.ts.map +1 -0
- package/dist/services/autostop/rule-registry.js +54 -0
- package/dist/services/autostop/rule-registry.js.map +1 -0
- package/dist/services/autostop/rules/consecutive-failures.rule.d.ts +38 -0
- package/dist/services/autostop/rules/consecutive-failures.rule.d.ts.map +1 -0
- package/dist/services/autostop/rules/consecutive-failures.rule.js +75 -0
- package/dist/services/autostop/rules/consecutive-failures.rule.js.map +1 -0
- package/dist/services/autostop/rules/idle-timeout.rule.d.ts +43 -0
- package/dist/services/autostop/rules/idle-timeout.rule.d.ts.map +1 -0
- package/dist/services/autostop/rules/idle-timeout.rule.js +128 -0
- package/dist/services/autostop/rules/idle-timeout.rule.js.map +1 -0
- package/dist/services/autostop/rules/unusual-activity.rule.d.ts +33 -0
- package/dist/services/autostop/rules/unusual-activity.rule.d.ts.map +1 -0
- package/dist/services/autostop/rules/unusual-activity.rule.js +73 -0
- package/dist/services/autostop/rules/unusual-activity.rule.js.map +1 -0
- package/dist/services/autostop/types.d.ts +49 -0
- package/dist/services/autostop/types.d.ts.map +1 -0
- package/dist/services/autostop/types.js +10 -0
- package/dist/services/autostop/types.js.map +1 -0
- package/dist/services/autostop-rules.d.ts +11 -74
- package/dist/services/autostop-rules.d.ts.map +1 -1
- package/dist/services/autostop-rules.js +9 -169
- package/dist/services/autostop-rules.js.map +1 -1
- package/dist/services/autostop-service.d.ts +6 -77
- package/dist/services/autostop-service.d.ts.map +1 -1
- package/dist/services/autostop-service.js +5 -212
- package/dist/services/autostop-service.js.map +1 -1
- package/dist/services/kill-switch-service.d.ts.map +1 -1
- package/dist/services/kill-switch-service.js +36 -21
- package/dist/services/kill-switch-service.js.map +1 -1
- package/dist/services/webhook-delivery-queue.d.ts +53 -0
- package/dist/services/webhook-delivery-queue.d.ts.map +1 -0
- package/dist/services/webhook-delivery-queue.js +118 -0
- package/dist/services/webhook-delivery-queue.js.map +1 -0
- package/dist/services/webhook-service.d.ts +46 -0
- package/dist/services/webhook-service.d.ts.map +1 -0
- package/dist/services/webhook-service.js +160 -0
- package/dist/services/webhook-service.js.map +1 -0
- package/package.json +5 -5
- package/public/admin/assets/{index-CBU6NfOH.js → index-RagPnRU1.js} +2 -2
- package/public/admin/index.html +1 -1
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AdminStatsService: aggregates 7-category operational statistics.
|
|
3
|
+
*
|
|
4
|
+
* Combines DB aggregate queries (transactions, sessions, wallets, notifications)
|
|
5
|
+
* with in-memory counters (RPC metrics) and service status (AutoStop, system info).
|
|
6
|
+
* Results are cached with a 1-minute TTL.
|
|
7
|
+
*
|
|
8
|
+
* @see STAT-01, STAT-02, STAT-03 requirements
|
|
9
|
+
*/
|
|
10
|
+
import { LATEST_SCHEMA_VERSION } from '../infrastructure/database/index.js';
|
|
11
|
+
import { statSync } from 'node:fs';
|
|
12
|
+
import { join } from 'node:path';
|
|
13
|
+
// ---------------------------------------------------------------------------
|
|
14
|
+
// AdminStatsService
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
export class AdminStatsService {
|
|
17
|
+
opts;
|
|
18
|
+
cache = null;
|
|
19
|
+
cacheExpiry = 0;
|
|
20
|
+
TTL_MS = 60_000; // 1 minute
|
|
21
|
+
constructor(opts) {
|
|
22
|
+
this.opts = opts;
|
|
23
|
+
}
|
|
24
|
+
/** Get aggregated stats. Returns cached value if within TTL. */
|
|
25
|
+
getStats() {
|
|
26
|
+
const now = Date.now();
|
|
27
|
+
if (this.cache && now < this.cacheExpiry) {
|
|
28
|
+
return this.cache;
|
|
29
|
+
}
|
|
30
|
+
const stats = this.buildStats();
|
|
31
|
+
this.cache = stats;
|
|
32
|
+
this.cacheExpiry = now + this.TTL_MS;
|
|
33
|
+
return stats;
|
|
34
|
+
}
|
|
35
|
+
/** Force cache refresh on next getStats() call. */
|
|
36
|
+
invalidateCache() {
|
|
37
|
+
this.cache = null;
|
|
38
|
+
}
|
|
39
|
+
// -----------------------------------------------------------------------
|
|
40
|
+
// Build stats
|
|
41
|
+
// -----------------------------------------------------------------------
|
|
42
|
+
buildStats() {
|
|
43
|
+
const sqlite = this.opts.sqlite;
|
|
44
|
+
const nowSec = Math.floor(Date.now() / 1000);
|
|
45
|
+
const day24h = nowSec - 86400;
|
|
46
|
+
const day7d = nowSec - 604800;
|
|
47
|
+
// 1. Transactions
|
|
48
|
+
const txTotal = sqlite.prepare('SELECT COUNT(*) as c FROM transactions').get().c;
|
|
49
|
+
const txByStatus = {};
|
|
50
|
+
const statusRows = sqlite.prepare('SELECT status, COUNT(*) as c FROM transactions GROUP BY status').all();
|
|
51
|
+
for (const row of statusRows) {
|
|
52
|
+
txByStatus[row.status] = row.c;
|
|
53
|
+
}
|
|
54
|
+
const txByType = {};
|
|
55
|
+
const typeRows = sqlite.prepare('SELECT type, COUNT(*) as c FROM transactions GROUP BY type').all();
|
|
56
|
+
for (const row of typeRows) {
|
|
57
|
+
txByType[row.type] = row.c;
|
|
58
|
+
}
|
|
59
|
+
const tx24h = sqlite.prepare('SELECT COUNT(*) as c, SUM(CASE WHEN amount_usd IS NOT NULL THEN amount_usd ELSE 0 END) as usd FROM transactions WHERE created_at >= ?').get(day24h);
|
|
60
|
+
const tx7d = sqlite.prepare('SELECT COUNT(*) as c, SUM(CASE WHEN amount_usd IS NOT NULL THEN amount_usd ELSE 0 END) as usd FROM transactions WHERE created_at >= ?').get(day7d);
|
|
61
|
+
// 2. Sessions
|
|
62
|
+
const sessTotal = sqlite.prepare('SELECT COUNT(*) as c FROM sessions').get().c;
|
|
63
|
+
const sessActive = sqlite.prepare('SELECT COUNT(*) as c FROM sessions WHERE revoked_at IS NULL AND expires_at > ?').get(nowSec).c;
|
|
64
|
+
const sessRevoked24h = sqlite.prepare('SELECT COUNT(*) as c FROM sessions WHERE revoked_at IS NOT NULL AND revoked_at >= ?').get(day24h).c;
|
|
65
|
+
// 3. Wallets
|
|
66
|
+
const walletTotal = sqlite.prepare('SELECT COUNT(*) as c FROM wallets').get().c;
|
|
67
|
+
const walletByStatus = {};
|
|
68
|
+
const walletStatusRows = sqlite.prepare('SELECT status, COUNT(*) as c FROM wallets GROUP BY status').all();
|
|
69
|
+
for (const row of walletStatusRows) {
|
|
70
|
+
walletByStatus[row.status] = row.c;
|
|
71
|
+
}
|
|
72
|
+
const walletWithOwner = sqlite.prepare('SELECT COUNT(*) as c FROM wallets WHERE owner_address IS NOT NULL').get().c;
|
|
73
|
+
// 4. RPC metrics from InMemoryCounter
|
|
74
|
+
const mc = this.opts.metricsCounter;
|
|
75
|
+
const rpcTotalCalls = mc.getCount('rpc.calls');
|
|
76
|
+
const rpcTotalErrors = mc.getCount('rpc.errors');
|
|
77
|
+
const rpcAvgLatency = mc.getAvgLatency('rpc.latency');
|
|
78
|
+
// Aggregate per-network RPC stats
|
|
79
|
+
const rpcCallsByNetwork = mc.getCountsByPrefix('rpc.calls|');
|
|
80
|
+
const rpcErrorsByNetwork = mc.getCountsByPrefix('rpc.errors|');
|
|
81
|
+
const rpcLatByNetwork = mc.getLatenciesByPrefix('rpc.latency|');
|
|
82
|
+
const networkSet = new Set();
|
|
83
|
+
for (const k of [...rpcCallsByNetwork.keys(), ...rpcErrorsByNetwork.keys(), ...rpcLatByNetwork.keys()]) {
|
|
84
|
+
const match = k.match(/network=([^|]+)/);
|
|
85
|
+
if (match?.[1])
|
|
86
|
+
networkSet.add(match[1]);
|
|
87
|
+
}
|
|
88
|
+
const byNetwork = Array.from(networkSet).map((network) => {
|
|
89
|
+
const calls = mc.getCount('rpc.calls', { network });
|
|
90
|
+
const errors = mc.getCount('rpc.errors', { network });
|
|
91
|
+
const avgLatencyMs = mc.getAvgLatency('rpc.latency', { network });
|
|
92
|
+
return { network, calls, errors, avgLatencyMs };
|
|
93
|
+
});
|
|
94
|
+
// 5. AutoStop
|
|
95
|
+
const autoStopStatus = this.opts.autoStopService?.getStatus();
|
|
96
|
+
const triggeredTotal = sqlite.prepare("SELECT COUNT(*) as c FROM audit_log WHERE event_type = 'AUTO_STOP_TRIGGERED'").get().c;
|
|
97
|
+
const lastTriggeredRow = sqlite.prepare("SELECT MAX(timestamp) as ts FROM audit_log WHERE event_type = 'AUTO_STOP_TRIGGERED'").get();
|
|
98
|
+
// Build rules list from registry if available
|
|
99
|
+
const registryRules = this.opts.autoStopService?.registry?.getRules();
|
|
100
|
+
const autoStopRules = registryRules
|
|
101
|
+
? registryRules.map((r) => ({
|
|
102
|
+
id: r.id,
|
|
103
|
+
displayName: r.displayName,
|
|
104
|
+
enabled: r.enabled,
|
|
105
|
+
trackedCount: r.getStatus().trackedCount,
|
|
106
|
+
}))
|
|
107
|
+
: [];
|
|
108
|
+
// 6. Notifications
|
|
109
|
+
let sentLast24h = 0;
|
|
110
|
+
let failedLast24h = 0;
|
|
111
|
+
try {
|
|
112
|
+
const notifRows = sqlite.prepare("SELECT status, COUNT(*) as c FROM notification_logs WHERE created_at >= ? GROUP BY status").all(day24h);
|
|
113
|
+
for (const row of notifRows) {
|
|
114
|
+
if (row.status === 'SENT' || row.status === 'sent')
|
|
115
|
+
sentLast24h += row.c;
|
|
116
|
+
if (row.status === 'FAILED' || row.status === 'failed')
|
|
117
|
+
failedLast24h += row.c;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
// notification_logs table may not exist in test environments
|
|
122
|
+
}
|
|
123
|
+
// 7. System
|
|
124
|
+
const uptimeSeconds = Math.floor((Date.now() - this.opts.startTime * 1000) / 1000);
|
|
125
|
+
let dbSizeBytes = 0;
|
|
126
|
+
if (this.opts.dataDir) {
|
|
127
|
+
try {
|
|
128
|
+
const dbPath = join(this.opts.dataDir, 'waiaas.db');
|
|
129
|
+
dbSizeBytes = statSync(dbPath).size;
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// DB file might not exist at that path
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
transactions: {
|
|
137
|
+
total: txTotal,
|
|
138
|
+
byStatus: txByStatus,
|
|
139
|
+
byType: txByType,
|
|
140
|
+
last24h: { count: tx24h.c, totalUsd: tx24h.usd },
|
|
141
|
+
last7d: { count: tx7d.c, totalUsd: tx7d.usd },
|
|
142
|
+
},
|
|
143
|
+
sessions: {
|
|
144
|
+
active: sessActive,
|
|
145
|
+
total: sessTotal,
|
|
146
|
+
revokedLast24h: sessRevoked24h,
|
|
147
|
+
},
|
|
148
|
+
wallets: {
|
|
149
|
+
total: walletTotal,
|
|
150
|
+
byStatus: walletByStatus,
|
|
151
|
+
withOwner: walletWithOwner,
|
|
152
|
+
},
|
|
153
|
+
rpc: {
|
|
154
|
+
totalCalls: rpcTotalCalls,
|
|
155
|
+
totalErrors: rpcTotalErrors,
|
|
156
|
+
avgLatencyMs: rpcAvgLatency,
|
|
157
|
+
byNetwork,
|
|
158
|
+
},
|
|
159
|
+
autostop: {
|
|
160
|
+
enabled: autoStopStatus?.enabled ?? false,
|
|
161
|
+
triggeredTotal,
|
|
162
|
+
rules: autoStopRules,
|
|
163
|
+
lastTriggeredAt: lastTriggeredRow?.ts ?? null,
|
|
164
|
+
},
|
|
165
|
+
notifications: {
|
|
166
|
+
sentLast24h,
|
|
167
|
+
failedLast24h,
|
|
168
|
+
channelStatus: {},
|
|
169
|
+
},
|
|
170
|
+
system: {
|
|
171
|
+
uptimeSeconds,
|
|
172
|
+
version: this.opts.version,
|
|
173
|
+
schemaVersion: LATEST_SCHEMA_VERSION,
|
|
174
|
+
dbSizeBytes,
|
|
175
|
+
nodeVersion: process.version,
|
|
176
|
+
platform: process.platform,
|
|
177
|
+
timestamp: nowSec,
|
|
178
|
+
},
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=admin-stats-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"admin-stats-service.js","sourceRoot":"","sources":["../../src/services/admin-stats-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AutoStopService: Registry-based anomaly detection engine with EventBus subscription.
|
|
3
|
+
*
|
|
4
|
+
* Refactored from direct rule references to RuleRegistry-based plugin architecture.
|
|
5
|
+
* The registry enables per-rule enable/disable, runtime config, and external API access.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* AUTO-01 CONSECUTIVE_FAILURES -- 5 consecutive tx failures -> wallet SUSPENDED
|
|
9
|
+
* AUTO-02 UNUSUAL_ACTIVITY -- High-frequency activity -> wallet SUSPENDED
|
|
10
|
+
* AUTO-03 IDLE_TIMEOUT -- Idle session -> auto-revoke
|
|
11
|
+
* AUTO-04 MANUAL_TRIGGER -- Manual trigger -> KillSwitch cascade
|
|
12
|
+
*
|
|
13
|
+
* @see PLUG-01, PLUG-02, AUTO-01~06 requirements
|
|
14
|
+
*/
|
|
15
|
+
import type { Database } from 'better-sqlite3';
|
|
16
|
+
import type { EventBus, IMetricsCounter } from '@waiaas/core';
|
|
17
|
+
import type { KillSwitchService } from '../kill-switch-service.js';
|
|
18
|
+
import type { NotificationService } from '../../notifications/notification-service.js';
|
|
19
|
+
import type { IRuleRegistry } from './rule-registry.js';
|
|
20
|
+
export interface AutoStopConfig {
|
|
21
|
+
consecutiveFailuresThreshold: number;
|
|
22
|
+
unusualActivityThreshold: number;
|
|
23
|
+
unusualActivityWindowSec: number;
|
|
24
|
+
idleTimeoutSec: number;
|
|
25
|
+
idleCheckIntervalSec: number;
|
|
26
|
+
enabled: boolean;
|
|
27
|
+
}
|
|
28
|
+
export declare const DEFAULT_AUTOSTOP_CONFIG: AutoStopConfig;
|
|
29
|
+
export declare class AutoStopService {
|
|
30
|
+
private sqlite;
|
|
31
|
+
private eventBus;
|
|
32
|
+
private killSwitchService;
|
|
33
|
+
private notificationService?;
|
|
34
|
+
private metricsCounter?;
|
|
35
|
+
private config;
|
|
36
|
+
private _registry;
|
|
37
|
+
private consecutiveFailuresRule;
|
|
38
|
+
private unusualActivityRule;
|
|
39
|
+
private idleTimeoutRule;
|
|
40
|
+
private idleCheckTimer;
|
|
41
|
+
constructor(opts: {
|
|
42
|
+
sqlite: Database;
|
|
43
|
+
eventBus: EventBus;
|
|
44
|
+
killSwitchService: KillSwitchService;
|
|
45
|
+
notificationService?: NotificationService;
|
|
46
|
+
config?: Partial<AutoStopConfig>;
|
|
47
|
+
});
|
|
48
|
+
/** Expose registry for external access (API routes, hot-reload). */
|
|
49
|
+
get registry(): IRuleRegistry;
|
|
50
|
+
/** Inject metrics counter after construction (daemon lifecycle order). */
|
|
51
|
+
setMetricsCounter(mc: IMetricsCounter): void;
|
|
52
|
+
/** Register EventBus listeners and start idle check timer. */
|
|
53
|
+
start(): void;
|
|
54
|
+
/** Stop idle check timer. Does NOT remove EventBus listeners (shared resource). */
|
|
55
|
+
stop(): void;
|
|
56
|
+
/** Manually trigger Kill Switch cascade. */
|
|
57
|
+
manualTrigger(triggeredBy: string): void;
|
|
58
|
+
/** Suspend a wallet and log the action. Only affects ACTIVE wallets. */
|
|
59
|
+
private suspendWallet;
|
|
60
|
+
/** Check idle sessions and send SESSION_IDLE notification instead of revoking. */
|
|
61
|
+
private checkIdleSessions;
|
|
62
|
+
/** Send SESSION_IDLE notification and remove from tracking to prevent duplicates (#204). */
|
|
63
|
+
private notifyIdleSession;
|
|
64
|
+
/** Update configuration at runtime (e.g., from Admin Settings). */
|
|
65
|
+
updateConfig(config: Partial<AutoStopConfig>): void;
|
|
66
|
+
/** Get current rule engine status for debugging/monitoring. */
|
|
67
|
+
getStatus(): {
|
|
68
|
+
enabled: boolean;
|
|
69
|
+
config: AutoStopConfig;
|
|
70
|
+
rules: {
|
|
71
|
+
consecutiveFailures: {
|
|
72
|
+
trackedWallets: number;
|
|
73
|
+
};
|
|
74
|
+
unusualActivity: {
|
|
75
|
+
trackedWallets: number;
|
|
76
|
+
};
|
|
77
|
+
idleTimeout: {
|
|
78
|
+
trackedSessions: number;
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=autostop-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autostop-service.d.ts","sourceRoot":"","sources":["../../../src/services/autostop/autostop-service.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC/C,OAAO,KAAK,EAAE,QAAQ,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AACnE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,6CAA6C,CAAC;AAGvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AASxD,MAAM,WAAW,cAAc;IAC7B,4BAA4B,EAAE,MAAM,CAAC;IACrC,wBAAwB,EAAE,MAAM,CAAC;IACjC,wBAAwB,EAAE,MAAM,CAAC;IACjC,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,eAAO,MAAM,uBAAuB,EAAE,cAOrC,CAAC;AAMF,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,mBAAmB,CAAC,CAAsB;IAClD,OAAO,CAAC,cAAc,CAAC,CAAkB;IACzC,OAAO,CAAC,MAAM,CAAiB;IAG/B,OAAO,CAAC,SAAS,CAAe;IAGhC,OAAO,CAAC,uBAAuB,CAA0B;IACzD,OAAO,CAAC,mBAAmB,CAAsB;IACjD,OAAO,CAAC,eAAe,CAAkB;IAGzC,OAAO,CAAC,cAAc,CAA+C;gBAEzD,IAAI,EAAE;QAChB,MAAM,EAAE,QAAQ,CAAC;QACjB,QAAQ,EAAE,QAAQ,CAAC;QACnB,iBAAiB,EAAE,iBAAiB,CAAC;QACrC,mBAAmB,CAAC,EAAE,mBAAmB,CAAC;QAC1C,MAAM,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;KAClC;IAwBD,oEAAoE;IACpE,IAAI,QAAQ,IAAI,aAAa,CAE5B;IAED,0EAA0E;IAC1E,iBAAiB,CAAC,EAAE,EAAE,eAAe,GAAG,IAAI;IAQ5C,8DAA8D;IAC9D,KAAK,IAAI,IAAI;IAkEb,mFAAmF;IACnF,IAAI,IAAI,IAAI;IAWZ,4CAA4C;IAC5C,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI;IAexC,wEAAwE;IACxE,OAAO,CAAC,aAAa;IA2CrB,kFAAkF;IAClF,OAAO,CAAC,iBAAiB;IASzB,4FAA4F;IAC5F,OAAO,CAAC,iBAAiB;IAgBzB,mEAAmE;IACnE,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,IAAI;IAyCnD,+DAA+D;IAC/D,SAAS,IAAI;QACX,OAAO,EAAE,OAAO,CAAC;QACjB,MAAM,EAAE,cAAc,CAAC;QACvB,KAAK,EAAE;YACL,mBAAmB,EAAE;gBAAE,cAAc,EAAE,MAAM,CAAA;aAAE,CAAC;YAChD,eAAe,EAAE;gBAAE,cAAc,EAAE,MAAM,CAAA;aAAE,CAAC;YAC5C,WAAW,EAAE;gBAAE,eAAe,EAAE,MAAM,CAAA;aAAE,CAAC;SAC1C,CAAC;KACH;CAiBF"}
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AutoStopService: Registry-based anomaly detection engine with EventBus subscription.
|
|
3
|
+
*
|
|
4
|
+
* Refactored from direct rule references to RuleRegistry-based plugin architecture.
|
|
5
|
+
* The registry enables per-rule enable/disable, runtime config, and external API access.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* AUTO-01 CONSECUTIVE_FAILURES -- 5 consecutive tx failures -> wallet SUSPENDED
|
|
9
|
+
* AUTO-02 UNUSUAL_ACTIVITY -- High-frequency activity -> wallet SUSPENDED
|
|
10
|
+
* AUTO-03 IDLE_TIMEOUT -- Idle session -> auto-revoke
|
|
11
|
+
* AUTO-04 MANUAL_TRIGGER -- Manual trigger -> KillSwitch cascade
|
|
12
|
+
*
|
|
13
|
+
* @see PLUG-01, PLUG-02, AUTO-01~06 requirements
|
|
14
|
+
*/
|
|
15
|
+
import { insertAuditLog } from '../../infrastructure/database/audit-helper.js';
|
|
16
|
+
import { RuleRegistry } from './rule-registry.js';
|
|
17
|
+
import { ConsecutiveFailuresRule } from './rules/consecutive-failures.rule.js';
|
|
18
|
+
import { UnusualActivityRule } from './rules/unusual-activity.rule.js';
|
|
19
|
+
import { IdleTimeoutRule } from './rules/idle-timeout.rule.js';
|
|
20
|
+
export const DEFAULT_AUTOSTOP_CONFIG = {
|
|
21
|
+
consecutiveFailuresThreshold: 5,
|
|
22
|
+
unusualActivityThreshold: 20,
|
|
23
|
+
unusualActivityWindowSec: 300,
|
|
24
|
+
idleTimeoutSec: 3600,
|
|
25
|
+
idleCheckIntervalSec: 60,
|
|
26
|
+
enabled: true,
|
|
27
|
+
};
|
|
28
|
+
// ---------------------------------------------------------------------------
|
|
29
|
+
// AutoStopService
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
export class AutoStopService {
|
|
32
|
+
sqlite;
|
|
33
|
+
eventBus;
|
|
34
|
+
killSwitchService;
|
|
35
|
+
notificationService;
|
|
36
|
+
metricsCounter;
|
|
37
|
+
config;
|
|
38
|
+
// Registry-based rule storage (PLUG-01)
|
|
39
|
+
_registry;
|
|
40
|
+
// Keep typed references for backward-compatible direct access
|
|
41
|
+
consecutiveFailuresRule;
|
|
42
|
+
unusualActivityRule;
|
|
43
|
+
idleTimeoutRule;
|
|
44
|
+
// Idle check timer
|
|
45
|
+
idleCheckTimer = null;
|
|
46
|
+
constructor(opts) {
|
|
47
|
+
this.sqlite = opts.sqlite;
|
|
48
|
+
this.eventBus = opts.eventBus;
|
|
49
|
+
this.killSwitchService = opts.killSwitchService;
|
|
50
|
+
this.notificationService = opts.notificationService;
|
|
51
|
+
this.config = { ...DEFAULT_AUTOSTOP_CONFIG, ...opts.config };
|
|
52
|
+
// Create rule instances with configured thresholds
|
|
53
|
+
this.consecutiveFailuresRule = new ConsecutiveFailuresRule(this.config.consecutiveFailuresThreshold);
|
|
54
|
+
this.unusualActivityRule = new UnusualActivityRule(this.config.unusualActivityThreshold, this.config.unusualActivityWindowSec);
|
|
55
|
+
this.idleTimeoutRule = new IdleTimeoutRule(this.config.idleTimeoutSec);
|
|
56
|
+
// Register all 3 builtin rules in the registry (PLUG-01)
|
|
57
|
+
this._registry = new RuleRegistry();
|
|
58
|
+
this._registry.register(this.consecutiveFailuresRule);
|
|
59
|
+
this._registry.register(this.unusualActivityRule);
|
|
60
|
+
this._registry.register(this.idleTimeoutRule);
|
|
61
|
+
}
|
|
62
|
+
/** Expose registry for external access (API routes, hot-reload). */
|
|
63
|
+
get registry() {
|
|
64
|
+
return this._registry;
|
|
65
|
+
}
|
|
66
|
+
/** Inject metrics counter after construction (daemon lifecycle order). */
|
|
67
|
+
setMetricsCounter(mc) {
|
|
68
|
+
this.metricsCounter = mc;
|
|
69
|
+
}
|
|
70
|
+
// -----------------------------------------------------------------------
|
|
71
|
+
// Lifecycle
|
|
72
|
+
// -----------------------------------------------------------------------
|
|
73
|
+
/** Register EventBus listeners and start idle check timer. */
|
|
74
|
+
start() {
|
|
75
|
+
if (!this.config.enabled)
|
|
76
|
+
return;
|
|
77
|
+
// AUTO-01: CONSECUTIVE_FAILURES
|
|
78
|
+
this.eventBus.on('transaction:failed', (data) => {
|
|
79
|
+
if (!this.consecutiveFailuresRule.enabled)
|
|
80
|
+
return;
|
|
81
|
+
const result = this.consecutiveFailuresRule.evaluate({
|
|
82
|
+
type: 'transaction:failed',
|
|
83
|
+
walletId: data.walletId,
|
|
84
|
+
timestamp: data.timestamp,
|
|
85
|
+
});
|
|
86
|
+
if (result.triggered) {
|
|
87
|
+
this.suspendWallet(result.walletId, 'CONSECUTIVE_FAILURES');
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
// Reset failure counter on successful transaction
|
|
91
|
+
this.eventBus.on('transaction:completed', (data) => {
|
|
92
|
+
if (!this.consecutiveFailuresRule.enabled)
|
|
93
|
+
return;
|
|
94
|
+
this.consecutiveFailuresRule.evaluate({
|
|
95
|
+
type: 'transaction:completed',
|
|
96
|
+
walletId: data.walletId,
|
|
97
|
+
timestamp: data.timestamp,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
// AUTO-02: UNUSUAL_ACTIVITY + AUTO-03: IdleTimeout session tracking
|
|
101
|
+
this.eventBus.on('wallet:activity', (data) => {
|
|
102
|
+
// UnusualActivityRule
|
|
103
|
+
if (this.unusualActivityRule.enabled) {
|
|
104
|
+
const result = this.unusualActivityRule.evaluate({
|
|
105
|
+
type: 'wallet:activity',
|
|
106
|
+
walletId: data.walletId,
|
|
107
|
+
timestamp: data.timestamp,
|
|
108
|
+
});
|
|
109
|
+
if (result.triggered) {
|
|
110
|
+
this.suspendWallet(result.walletId, 'UNUSUAL_ACTIVITY');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
// IdleTimeoutRule: register new sessions or update activity
|
|
114
|
+
if (this.idleTimeoutRule.enabled) {
|
|
115
|
+
if (data.activity === 'SESSION_CREATED' && data.details?.sessionId) {
|
|
116
|
+
this.idleTimeoutRule.registerSession(data.walletId, data.details.sessionId, data.timestamp);
|
|
117
|
+
}
|
|
118
|
+
else if (data.details?.sessionId) {
|
|
119
|
+
this.idleTimeoutRule.onWalletActivity(data.walletId, data.timestamp, data.details.sessionId);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
this.idleTimeoutRule.onWalletActivity(data.walletId, data.timestamp);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
// AUTO-03: Periodic idle session check
|
|
127
|
+
this.idleCheckTimer = setInterval(() => {
|
|
128
|
+
this.checkIdleSessions();
|
|
129
|
+
}, this.config.idleCheckIntervalSec * 1000);
|
|
130
|
+
}
|
|
131
|
+
/** Stop idle check timer. Does NOT remove EventBus listeners (shared resource). */
|
|
132
|
+
stop() {
|
|
133
|
+
if (this.idleCheckTimer) {
|
|
134
|
+
clearInterval(this.idleCheckTimer);
|
|
135
|
+
this.idleCheckTimer = null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
// -----------------------------------------------------------------------
|
|
139
|
+
// AUTO-04: Manual Trigger
|
|
140
|
+
// -----------------------------------------------------------------------
|
|
141
|
+
/** Manually trigger Kill Switch cascade. */
|
|
142
|
+
manualTrigger(triggeredBy) {
|
|
143
|
+
this.killSwitchService.activateWithCascade(triggeredBy);
|
|
144
|
+
// Fire-and-forget notification (AUTO-06)
|
|
145
|
+
void this.notificationService?.notify('AUTO_STOP_TRIGGERED', 'system', { walletId: 'system', reason: 'Manual trigger by ' + triggeredBy, rule: 'MANUAL_TRIGGER' });
|
|
146
|
+
}
|
|
147
|
+
// -----------------------------------------------------------------------
|
|
148
|
+
// Wallet suspension (AUTO-01, AUTO-02)
|
|
149
|
+
// -----------------------------------------------------------------------
|
|
150
|
+
/** Suspend a wallet and log the action. Only affects ACTIVE wallets. */
|
|
151
|
+
suspendWallet(walletId, reason) {
|
|
152
|
+
const now = Math.floor(Date.now() / 1000);
|
|
153
|
+
const result = this.sqlite
|
|
154
|
+
.prepare("UPDATE wallets SET status = 'SUSPENDED', suspended_at = ?, suspension_reason = ? WHERE id = ? AND status = 'ACTIVE'")
|
|
155
|
+
.run(now, reason, walletId);
|
|
156
|
+
if (result.changes === 0) {
|
|
157
|
+
// Wallet already suspended or not found -- skip notification/audit
|
|
158
|
+
// Still reset counter to prevent re-checking
|
|
159
|
+
this.consecutiveFailuresRule.resetWallet(walletId);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
// Reset failure counter after trigger (must accumulate N new failures to re-trigger)
|
|
163
|
+
this.consecutiveFailuresRule.resetWallet(walletId);
|
|
164
|
+
// Audit log (best-effort via helper)
|
|
165
|
+
insertAuditLog(this.sqlite, {
|
|
166
|
+
eventType: 'AUTO_STOP_TRIGGERED',
|
|
167
|
+
actor: 'autostop',
|
|
168
|
+
walletId,
|
|
169
|
+
details: { action: 'wallet_suspended', reason, walletId },
|
|
170
|
+
severity: 'warning',
|
|
171
|
+
});
|
|
172
|
+
// v30.2: increment autostop.triggered counter (STAT-02)
|
|
173
|
+
this.metricsCounter?.increment('autostop.triggered', { rule: reason });
|
|
174
|
+
// Fire-and-forget notification (AUTO-06)
|
|
175
|
+
void this.notificationService?.notify('AUTO_STOP_TRIGGERED', walletId, { walletId, reason, rule: reason });
|
|
176
|
+
}
|
|
177
|
+
// -----------------------------------------------------------------------
|
|
178
|
+
// Session idle detection (AUTO-03) -- notify only, no revoke (#204)
|
|
179
|
+
// -----------------------------------------------------------------------
|
|
180
|
+
/** Check idle sessions and send SESSION_IDLE notification instead of revoking. */
|
|
181
|
+
checkIdleSessions() {
|
|
182
|
+
const now = Math.floor(Date.now() / 1000);
|
|
183
|
+
const idleSessions = this.idleTimeoutRule.checkIdle(now);
|
|
184
|
+
for (const { walletId, sessionId } of idleSessions) {
|
|
185
|
+
this.notifyIdleSession(walletId, sessionId);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
/** Send SESSION_IDLE notification and remove from tracking to prevent duplicates (#204). */
|
|
189
|
+
notifyIdleSession(walletId, sessionId) {
|
|
190
|
+
// Remove from tracking to prevent duplicate notifications
|
|
191
|
+
this.idleTimeoutRule.removeSession(walletId, sessionId);
|
|
192
|
+
// Fire-and-forget notification
|
|
193
|
+
void this.notificationService?.notify('SESSION_IDLE', walletId, { walletId, sessionId, reason: 'Idle session detected' });
|
|
194
|
+
}
|
|
195
|
+
// -----------------------------------------------------------------------
|
|
196
|
+
// Runtime configuration update (AUTO-05)
|
|
197
|
+
// -----------------------------------------------------------------------
|
|
198
|
+
/** Update configuration at runtime (e.g., from Admin Settings). */
|
|
199
|
+
updateConfig(config) {
|
|
200
|
+
if (config.consecutiveFailuresThreshold !== undefined) {
|
|
201
|
+
this.config.consecutiveFailuresThreshold = config.consecutiveFailuresThreshold;
|
|
202
|
+
this.consecutiveFailuresRule.updateConfig({ threshold: config.consecutiveFailuresThreshold });
|
|
203
|
+
}
|
|
204
|
+
if (config.unusualActivityThreshold !== undefined) {
|
|
205
|
+
this.config.unusualActivityThreshold = config.unusualActivityThreshold;
|
|
206
|
+
this.unusualActivityRule.updateConfig({ threshold: config.unusualActivityThreshold });
|
|
207
|
+
}
|
|
208
|
+
if (config.unusualActivityWindowSec !== undefined) {
|
|
209
|
+
this.config.unusualActivityWindowSec = config.unusualActivityWindowSec;
|
|
210
|
+
this.unusualActivityRule.updateConfig({ windowSec: config.unusualActivityWindowSec });
|
|
211
|
+
}
|
|
212
|
+
if (config.idleTimeoutSec !== undefined) {
|
|
213
|
+
this.config.idleTimeoutSec = config.idleTimeoutSec;
|
|
214
|
+
this.idleTimeoutRule.updateConfig({ idleTimeoutSec: config.idleTimeoutSec });
|
|
215
|
+
}
|
|
216
|
+
if (config.idleCheckIntervalSec !== undefined) {
|
|
217
|
+
this.config.idleCheckIntervalSec = config.idleCheckIntervalSec;
|
|
218
|
+
// Restart timer with new interval
|
|
219
|
+
if (this.idleCheckTimer) {
|
|
220
|
+
clearInterval(this.idleCheckTimer);
|
|
221
|
+
this.idleCheckTimer = setInterval(() => {
|
|
222
|
+
this.checkIdleSessions();
|
|
223
|
+
}, config.idleCheckIntervalSec * 1000);
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (config.enabled !== undefined) {
|
|
227
|
+
this.config.enabled = config.enabled;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
// -----------------------------------------------------------------------
|
|
231
|
+
// Monitoring / status
|
|
232
|
+
// -----------------------------------------------------------------------
|
|
233
|
+
/** Get current rule engine status for debugging/monitoring. */
|
|
234
|
+
getStatus() {
|
|
235
|
+
return {
|
|
236
|
+
enabled: this.config.enabled,
|
|
237
|
+
config: { ...this.config },
|
|
238
|
+
rules: {
|
|
239
|
+
consecutiveFailures: {
|
|
240
|
+
trackedWallets: this.consecutiveFailuresRule.getStatus().trackedCount,
|
|
241
|
+
},
|
|
242
|
+
unusualActivity: {
|
|
243
|
+
trackedWallets: this.unusualActivityRule.getStatus().trackedCount,
|
|
244
|
+
},
|
|
245
|
+
idleTimeout: {
|
|
246
|
+
trackedSessions: this.idleTimeoutRule.getStatus().trackedCount,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
//# sourceMappingURL=autostop-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autostop-service.js","sourceRoot":"","sources":["../../../src/services/autostop/autostop-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AutoStop plugin module barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports types, registry, service, and individual rule implementations.
|
|
5
|
+
*/
|
|
6
|
+
export type { IAutoStopRule, AutoStopEventType, AutoStopEvent, RuleResult, RuleAction, RuleTickResult, RuleStatus, } from './types.js';
|
|
7
|
+
export type { IRuleRegistry } from './rule-registry.js';
|
|
8
|
+
export { RuleRegistry } from './rule-registry.js';
|
|
9
|
+
export { AutoStopService, DEFAULT_AUTOSTOP_CONFIG } from './autostop-service.js';
|
|
10
|
+
export type { AutoStopConfig } from './autostop-service.js';
|
|
11
|
+
export { ConsecutiveFailuresRule } from './rules/consecutive-failures.rule.js';
|
|
12
|
+
export { UnusualActivityRule } from './rules/unusual-activity.rule.js';
|
|
13
|
+
export { IdleTimeoutRule } from './rules/idle-timeout.rule.js';
|
|
14
|
+
export type { IdleSession } from './rules/idle-timeout.rule.js';
|
|
15
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/autostop/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,YAAY,EACV,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,UAAU,EACV,UAAU,EACV,cAAc,EACd,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AACjF,YAAY,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,YAAY,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AutoStop plugin module barrel export.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports types, registry, service, and individual rule implementations.
|
|
5
|
+
*/
|
|
6
|
+
export { RuleRegistry } from './rule-registry.js';
|
|
7
|
+
export { AutoStopService, DEFAULT_AUTOSTOP_CONFIG } from './autostop-service.js';
|
|
8
|
+
export { ConsecutiveFailuresRule } from './rules/consecutive-failures.rule.js';
|
|
9
|
+
export { UnusualActivityRule } from './rules/unusual-activity.rule.js';
|
|
10
|
+
export { IdleTimeoutRule } from './rules/idle-timeout.rule.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/services/autostop/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAaH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAC;AAGjF,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RuleRegistry: Map-based storage for IAutoStopRule instances.
|
|
3
|
+
*
|
|
4
|
+
* Supports register/unregister, enable/disable per-rule, and
|
|
5
|
+
* query by event type or tickable capability.
|
|
6
|
+
*
|
|
7
|
+
* @see PLUG-01 requirements
|
|
8
|
+
*/
|
|
9
|
+
import type { IAutoStopRule, AutoStopEventType } from './types.js';
|
|
10
|
+
export interface IRuleRegistry {
|
|
11
|
+
register(rule: IAutoStopRule): void;
|
|
12
|
+
unregister(ruleId: string): void;
|
|
13
|
+
getRules(): IAutoStopRule[];
|
|
14
|
+
getRule(id: string): IAutoStopRule | undefined;
|
|
15
|
+
getEnabledRules(): IAutoStopRule[];
|
|
16
|
+
getRulesForEvent(eventType: AutoStopEventType): IAutoStopRule[];
|
|
17
|
+
getTickableRules(): IAutoStopRule[];
|
|
18
|
+
setEnabled(ruleId: string, enabled: boolean): void;
|
|
19
|
+
readonly size: number;
|
|
20
|
+
}
|
|
21
|
+
export declare class RuleRegistry implements IRuleRegistry {
|
|
22
|
+
private rules;
|
|
23
|
+
/** Register a rule (replaces existing rule with same id). */
|
|
24
|
+
register(rule: IAutoStopRule): void;
|
|
25
|
+
/** Unregister a rule by id. */
|
|
26
|
+
unregister(ruleId: string): void;
|
|
27
|
+
/** Get all rules in insertion order. */
|
|
28
|
+
getRules(): IAutoStopRule[];
|
|
29
|
+
/** Get a single rule by id. */
|
|
30
|
+
getRule(id: string): IAutoStopRule | undefined;
|
|
31
|
+
/** Get only enabled rules. */
|
|
32
|
+
getEnabledRules(): IAutoStopRule[];
|
|
33
|
+
/** Get enabled rules that subscribe to the given event type. */
|
|
34
|
+
getRulesForEvent(eventType: AutoStopEventType): IAutoStopRule[];
|
|
35
|
+
/** Get enabled rules that have a tick() method. */
|
|
36
|
+
getTickableRules(): IAutoStopRule[];
|
|
37
|
+
/** Set enabled state for a specific rule. */
|
|
38
|
+
setEnabled(ruleId: string, enabled: boolean): void;
|
|
39
|
+
/** Number of registered rules. */
|
|
40
|
+
get size(): number;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=rule-registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rule-registry.d.ts","sourceRoot":"","sources":["../../../src/services/autostop/rule-registry.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAMnE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI,CAAC;IACpC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,IAAI,aAAa,EAAE,CAAC;IAC5B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAAC;IAC/C,eAAe,IAAI,aAAa,EAAE,CAAC;IACnC,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,GAAG,aAAa,EAAE,CAAC;IAChE,gBAAgB,IAAI,aAAa,EAAE,CAAC;IACpC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;IACnD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAMD,qBAAa,YAAa,YAAW,aAAa;IAChD,OAAO,CAAC,KAAK,CAAoC;IAEjD,6DAA6D;IAC7D,QAAQ,CAAC,IAAI,EAAE,aAAa,GAAG,IAAI;IAInC,+BAA+B;IAC/B,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI;IAIhC,wCAAwC;IACxC,QAAQ,IAAI,aAAa,EAAE;IAI3B,+BAA+B;IAC/B,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS;IAI9C,8BAA8B;IAC9B,eAAe,IAAI,aAAa,EAAE;IAIlC,gEAAgE;IAChE,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,GAAG,aAAa,EAAE;IAI/D,mDAAmD;IACnD,gBAAgB,IAAI,aAAa,EAAE;IAInC,6CAA6C;IAC7C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI;IAOlD,kCAAkC;IAClC,IAAI,IAAI,IAAI,MAAM,CAEjB;CACF"}
|