@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.
Files changed (163) hide show
  1. package/dist/api/middleware/master-auth.d.ts +3 -0
  2. package/dist/api/middleware/master-auth.d.ts.map +1 -1
  3. package/dist/api/middleware/master-auth.js +14 -0
  4. package/dist/api/middleware/master-auth.js.map +1 -1
  5. package/dist/api/routes/admin.d.ts +4 -0
  6. package/dist/api/routes/admin.d.ts.map +1 -1
  7. package/dist/api/routes/admin.js +186 -1
  8. package/dist/api/routes/admin.js.map +1 -1
  9. package/dist/api/routes/audit-logs.d.ts +15 -0
  10. package/dist/api/routes/audit-logs.d.ts.map +1 -0
  11. package/dist/api/routes/audit-logs.js +119 -0
  12. package/dist/api/routes/audit-logs.js.map +1 -0
  13. package/dist/api/routes/index.d.ts +2 -1
  14. package/dist/api/routes/index.d.ts.map +1 -1
  15. package/dist/api/routes/index.js +2 -1
  16. package/dist/api/routes/index.js.map +1 -1
  17. package/dist/api/routes/openapi-schemas.d.ts +324 -6
  18. package/dist/api/routes/openapi-schemas.d.ts.map +1 -1
  19. package/dist/api/routes/openapi-schemas.js +76 -0
  20. package/dist/api/routes/openapi-schemas.js.map +1 -1
  21. package/dist/api/routes/sessions.d.ts +2 -0
  22. package/dist/api/routes/sessions.d.ts.map +1 -1
  23. package/dist/api/routes/sessions.js +21 -0
  24. package/dist/api/routes/sessions.js.map +1 -1
  25. package/dist/api/routes/transactions.d.ts +2 -1
  26. package/dist/api/routes/transactions.d.ts.map +1 -1
  27. package/dist/api/routes/transactions.js +72 -1
  28. package/dist/api/routes/transactions.js.map +1 -1
  29. package/dist/api/routes/wallets.d.ts.map +1 -1
  30. package/dist/api/routes/wallets.js +25 -0
  31. package/dist/api/routes/wallets.js.map +1 -1
  32. package/dist/api/routes/webhooks.d.ts +17 -0
  33. package/dist/api/routes/webhooks.d.ts.map +1 -0
  34. package/dist/api/routes/webhooks.js +218 -0
  35. package/dist/api/routes/webhooks.js.map +1 -0
  36. package/dist/api/server.d.ts +27 -0
  37. package/dist/api/server.d.ts.map +1 -1
  38. package/dist/api/server.js +31 -5
  39. package/dist/api/server.js.map +1 -1
  40. package/dist/index.d.ts +3 -0
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +2 -0
  43. package/dist/index.js.map +1 -1
  44. package/dist/infrastructure/backup/backup-format.d.ts +107 -0
  45. package/dist/infrastructure/backup/backup-format.d.ts.map +1 -0
  46. package/dist/infrastructure/backup/backup-format.js +134 -0
  47. package/dist/infrastructure/backup/backup-format.js.map +1 -0
  48. package/dist/infrastructure/backup/encrypted-backup-service.d.ts +56 -0
  49. package/dist/infrastructure/backup/encrypted-backup-service.d.ts.map +1 -0
  50. package/dist/infrastructure/backup/encrypted-backup-service.js +269 -0
  51. package/dist/infrastructure/backup/encrypted-backup-service.js.map +1 -0
  52. package/dist/infrastructure/backup/index.d.ts +3 -0
  53. package/dist/infrastructure/backup/index.d.ts.map +1 -1
  54. package/dist/infrastructure/backup/index.js +2 -0
  55. package/dist/infrastructure/backup/index.js.map +1 -1
  56. package/dist/infrastructure/config/loader.d.ts +23 -0
  57. package/dist/infrastructure/config/loader.d.ts.map +1 -1
  58. package/dist/infrastructure/config/loader.js +8 -0
  59. package/dist/infrastructure/config/loader.js.map +1 -1
  60. package/dist/infrastructure/database/audit-helper.d.ts +29 -0
  61. package/dist/infrastructure/database/audit-helper.d.ts.map +1 -0
  62. package/dist/infrastructure/database/audit-helper.js +30 -0
  63. package/dist/infrastructure/database/audit-helper.js.map +1 -0
  64. package/dist/infrastructure/database/index.d.ts +2 -0
  65. package/dist/infrastructure/database/index.d.ts.map +1 -1
  66. package/dist/infrastructure/database/index.js +1 -0
  67. package/dist/infrastructure/database/index.js.map +1 -1
  68. package/dist/infrastructure/database/migrate.d.ts +1 -1
  69. package/dist/infrastructure/database/migrate.d.ts.map +1 -1
  70. package/dist/infrastructure/database/migrate.js +83 -2
  71. package/dist/infrastructure/database/migrate.js.map +1 -1
  72. package/dist/infrastructure/database/schema.d.ts +343 -1
  73. package/dist/infrastructure/database/schema.d.ts.map +1 -1
  74. package/dist/infrastructure/database/schema.js +41 -1
  75. package/dist/infrastructure/database/schema.js.map +1 -1
  76. package/dist/infrastructure/metrics/in-memory-counter.d.ts +34 -0
  77. package/dist/infrastructure/metrics/in-memory-counter.d.ts.map +1 -0
  78. package/dist/infrastructure/metrics/in-memory-counter.js +88 -0
  79. package/dist/infrastructure/metrics/in-memory-counter.js.map +1 -0
  80. package/dist/infrastructure/settings/hot-reload.d.ts +1 -0
  81. package/dist/infrastructure/settings/hot-reload.d.ts.map +1 -1
  82. package/dist/infrastructure/settings/hot-reload.js +23 -2
  83. package/dist/infrastructure/settings/hot-reload.js.map +1 -1
  84. package/dist/infrastructure/settings/setting-keys.d.ts.map +1 -1
  85. package/dist/infrastructure/settings/setting-keys.js +4 -0
  86. package/dist/infrastructure/settings/setting-keys.js.map +1 -1
  87. package/dist/infrastructure/telegram/telegram-bot-service.d.ts.map +1 -1
  88. package/dist/infrastructure/telegram/telegram-bot-service.js +32 -19
  89. package/dist/infrastructure/telegram/telegram-bot-service.js.map +1 -1
  90. package/dist/lifecycle/daemon.d.ts +8 -1
  91. package/dist/lifecycle/daemon.d.ts.map +1 -1
  92. package/dist/lifecycle/daemon.js +103 -1
  93. package/dist/lifecycle/daemon.js.map +1 -1
  94. package/dist/pipeline/dry-run.d.ts +68 -0
  95. package/dist/pipeline/dry-run.d.ts.map +1 -0
  96. package/dist/pipeline/dry-run.js +426 -0
  97. package/dist/pipeline/dry-run.js.map +1 -0
  98. package/dist/pipeline/index.d.ts +1 -0
  99. package/dist/pipeline/index.d.ts.map +1 -1
  100. package/dist/pipeline/index.js +2 -0
  101. package/dist/pipeline/index.js.map +1 -1
  102. package/dist/pipeline/pipeline.d.ts +18 -1
  103. package/dist/pipeline/pipeline.d.ts.map +1 -1
  104. package/dist/pipeline/pipeline.js +38 -0
  105. package/dist/pipeline/pipeline.js.map +1 -1
  106. package/dist/pipeline/stages.d.ts +31 -1
  107. package/dist/pipeline/stages.d.ts.map +1 -1
  108. package/dist/pipeline/stages.js +120 -22
  109. package/dist/pipeline/stages.js.map +1 -1
  110. package/dist/services/admin-stats-service.d.ts +48 -0
  111. package/dist/services/admin-stats-service.d.ts.map +1 -0
  112. package/dist/services/admin-stats-service.js +182 -0
  113. package/dist/services/admin-stats-service.js.map +1 -0
  114. package/dist/services/autostop/autostop-service.d.ts +83 -0
  115. package/dist/services/autostop/autostop-service.d.ts.map +1 -0
  116. package/dist/services/autostop/autostop-service.js +252 -0
  117. package/dist/services/autostop/autostop-service.js.map +1 -0
  118. package/dist/services/autostop/index.d.ts +15 -0
  119. package/dist/services/autostop/index.d.ts.map +1 -0
  120. package/dist/services/autostop/index.js +11 -0
  121. package/dist/services/autostop/index.js.map +1 -0
  122. package/dist/services/autostop/rule-registry.d.ts +42 -0
  123. package/dist/services/autostop/rule-registry.d.ts.map +1 -0
  124. package/dist/services/autostop/rule-registry.js +54 -0
  125. package/dist/services/autostop/rule-registry.js.map +1 -0
  126. package/dist/services/autostop/rules/consecutive-failures.rule.d.ts +38 -0
  127. package/dist/services/autostop/rules/consecutive-failures.rule.d.ts.map +1 -0
  128. package/dist/services/autostop/rules/consecutive-failures.rule.js +75 -0
  129. package/dist/services/autostop/rules/consecutive-failures.rule.js.map +1 -0
  130. package/dist/services/autostop/rules/idle-timeout.rule.d.ts +43 -0
  131. package/dist/services/autostop/rules/idle-timeout.rule.d.ts.map +1 -0
  132. package/dist/services/autostop/rules/idle-timeout.rule.js +128 -0
  133. package/dist/services/autostop/rules/idle-timeout.rule.js.map +1 -0
  134. package/dist/services/autostop/rules/unusual-activity.rule.d.ts +33 -0
  135. package/dist/services/autostop/rules/unusual-activity.rule.d.ts.map +1 -0
  136. package/dist/services/autostop/rules/unusual-activity.rule.js +73 -0
  137. package/dist/services/autostop/rules/unusual-activity.rule.js.map +1 -0
  138. package/dist/services/autostop/types.d.ts +49 -0
  139. package/dist/services/autostop/types.d.ts.map +1 -0
  140. package/dist/services/autostop/types.js +10 -0
  141. package/dist/services/autostop/types.js.map +1 -0
  142. package/dist/services/autostop-rules.d.ts +11 -74
  143. package/dist/services/autostop-rules.d.ts.map +1 -1
  144. package/dist/services/autostop-rules.js +9 -169
  145. package/dist/services/autostop-rules.js.map +1 -1
  146. package/dist/services/autostop-service.d.ts +6 -77
  147. package/dist/services/autostop-service.d.ts.map +1 -1
  148. package/dist/services/autostop-service.js +5 -212
  149. package/dist/services/autostop-service.js.map +1 -1
  150. package/dist/services/kill-switch-service.d.ts.map +1 -1
  151. package/dist/services/kill-switch-service.js +36 -21
  152. package/dist/services/kill-switch-service.js.map +1 -1
  153. package/dist/services/webhook-delivery-queue.d.ts +53 -0
  154. package/dist/services/webhook-delivery-queue.d.ts.map +1 -0
  155. package/dist/services/webhook-delivery-queue.js +118 -0
  156. package/dist/services/webhook-delivery-queue.js.map +1 -0
  157. package/dist/services/webhook-service.d.ts +46 -0
  158. package/dist/services/webhook-service.d.ts.map +1 -0
  159. package/dist/services/webhook-service.js +160 -0
  160. package/dist/services/webhook-service.js.map +1 -0
  161. package/package.json +5 -5
  162. package/public/admin/assets/{index-CBU6NfOH.js → index-RagPnRU1.js} +2 -2
  163. 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":"AAAA;;;;;;;;;;;;;GAaG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,+CAA+C,CAAC;AAC/E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,uBAAuB,EAAE,MAAM,sCAAsC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,kCAAkC,CAAC;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAe/D,MAAM,CAAC,MAAM,uBAAuB,GAAmB;IACrD,4BAA4B,EAAE,CAAC;IAC/B,wBAAwB,EAAE,EAAE;IAC5B,wBAAwB,EAAE,GAAG;IAC7B,cAAc,EAAE,IAAI;IACpB,oBAAoB,EAAE,EAAE;IACxB,OAAO,EAAE,IAAI;CACd,CAAC;AAEF,8EAA8E;AAC9E,kBAAkB;AAClB,8EAA8E;AAE9E,MAAM,OAAO,eAAe;IAClB,MAAM,CAAW;IACjB,QAAQ,CAAW;IACnB,iBAAiB,CAAoB;IACrC,mBAAmB,CAAuB;IAC1C,cAAc,CAAmB;IACjC,MAAM,CAAiB;IAE/B,wCAAwC;IAChC,SAAS,CAAe;IAEhC,8DAA8D;IACtD,uBAAuB,CAA0B;IACjD,mBAAmB,CAAsB;IACzC,eAAe,CAAkB;IAEzC,mBAAmB;IACX,cAAc,GAA0C,IAAI,CAAC;IAErE,YAAY,IAMX;QACC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;QAC9B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,CAAC;QAChD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACpD,IAAI,CAAC,MAAM,GAAG,EAAE,GAAG,uBAAuB,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC;QAE7D,mDAAmD;QACnD,IAAI,CAAC,uBAAuB,GAAG,IAAI,uBAAuB,CACxD,IAAI,CAAC,MAAM,CAAC,4BAA4B,CACzC,CAAC;QACF,IAAI,CAAC,mBAAmB,GAAG,IAAI,mBAAmB,CAChD,IAAI,CAAC,MAAM,CAAC,wBAAwB,EACpC,IAAI,CAAC,MAAM,CAAC,wBAAwB,CACrC,CAAC;QACF,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAEvE,yDAAyD;QACzD,IAAI,CAAC,SAAS,GAAG,IAAI,YAAY,EAAE,CAAC;QACpC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC;QACtD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC;QAClD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChD,CAAC;IAED,oEAAoE;IACpE,IAAI,QAAQ;QACV,OAAO,IAAI,CAAC,SAAS,CAAC;IACxB,CAAC;IAED,0EAA0E;IAC1E,iBAAiB,CAAC,EAAmB;QACnC,IAAI,CAAC,cAAc,GAAG,EAAE,CAAC;IAC3B,CAAC;IAED,0EAA0E;IAC1E,YAAY;IACZ,0EAA0E;IAE1E,8DAA8D;IAC9D,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO;QAEjC,gCAAgC;QAChC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,oBAAoB,EAAE,CAAC,IAAI,EAAE,EAAE;YAC9C,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,OAAO;gBAAE,OAAO;YAClD,MAAM,MAAM,GAAG,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC;gBACnD,IAAI,EAAE,oBAAoB;gBAC1B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC;YACH,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;gBACrB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,sBAAsB,CAAC,CAAC;YAC9D,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,kDAAkD;QAClD,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,uBAAuB,EAAE,CAAC,IAAI,EAAE,EAAE;YACjD,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAC,OAAO;gBAAE,OAAO;YAClD,IAAI,CAAC,uBAAuB,CAAC,QAAQ,CAAC;gBACpC,IAAI,EAAE,uBAAuB;gBAC7B,QAAQ,EAAE,IAAI,CAAC,QAAQ;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,oEAAoE;QACpE,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,iBAAiB,EAAE,CAAC,IAAI,EAAE,EAAE;YAC3C,sBAAsB;YACtB,IAAI,IAAI,CAAC,mBAAmB,CAAC,OAAO,EAAE,CAAC;gBACrC,MAAM,MAAM,GAAG,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC;oBAC/C,IAAI,EAAE,iBAAiB;oBACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;oBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;iBAC1B,CAAC,CAAC;gBACH,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;oBACrB,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;gBAC1D,CAAC;YACH,CAAC;YAED,4DAA4D;YAC5D,IAAI,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,QAAQ,KAAK,iBAAiB,IAAI,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;oBACnE,IAAI,CAAC,eAAe,CAAC,eAAe,CAClC,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,OAAO,CAAC,SAAmB,EAChC,IAAI,CAAC,SAAS,CACf,CAAC;gBACJ,CAAC;qBAAM,IAAI,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC;oBACnC,IAAI,CAAC,eAAe,CAAC,gBAAgB,CACnC,IAAI,CAAC,QAAQ,EACb,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,OAAO,CAAC,SAAmB,CACjC,CAAC;gBACJ,CAAC;qBAAM,CAAC;oBACN,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;gBACvE,CAAC;YACH,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,uCAAuC;QACvC,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;YACrC,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED,mFAAmF;IACnF,IAAI;QACF,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;YACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;YACnC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC;QAC7B,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,0BAA0B;IAC1B,0EAA0E;IAE1E,4CAA4C;IAC5C,aAAa,CAAC,WAAmB;QAC/B,IAAI,CAAC,iBAAiB,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC;QAExD,yCAAyC;QACzC,KAAK,IAAI,CAAC,mBAAmB,EAAE,MAAM,CACnC,qBAAqE,EACrE,QAAQ,EACR,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,oBAAoB,GAAG,WAAW,EAAE,IAAI,EAAE,gBAAgB,EAAE,CAC3F,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,uCAAuC;IACvC,0EAA0E;IAE1E,wEAAwE;IAChE,aAAa,CAAC,QAAgB,EAAE,MAAc;QACpD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAE1C,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM;aACvB,OAAO,CACN,qHAAqH,CACtH;aACA,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;QAE9B,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE,CAAC;YACzB,mEAAmE;YACnE,6CAA6C;YAC7C,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;YACnD,OAAO;QACT,CAAC;QAED,qFAAqF;QACrF,IAAI,CAAC,uBAAuB,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAEnD,qCAAqC;QACrC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE;YAC1B,SAAS,EAAE,qBAAqB;YAChC,KAAK,EAAE,UAAU;YACjB,QAAQ;YACR,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,EAAE,QAAQ,EAAE;YACzD,QAAQ,EAAE,SAAS;SACpB,CAAC,CAAC;QAEH,wDAAwD;QACxD,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC,oBAAoB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAEvE,yCAAyC;QACzC,KAAK,IAAI,CAAC,mBAAmB,EAAE,MAAM,CACnC,qBAAqE,EACrE,QAAQ,EACR,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,CACnC,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,oEAAoE;IACpE,0EAA0E;IAE1E,kFAAkF;IAC1E,iBAAiB;QACvB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,MAAM,YAAY,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAEzD,KAAK,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,IAAI,YAAY,EAAE,CAAC;YACnD,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,4FAA4F;IACpF,iBAAiB,CAAC,QAAgB,EAAE,SAAiB;QAC3D,0DAA0D;QAC1D,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;QAExD,+BAA+B;QAC/B,KAAK,IAAI,CAAC,mBAAmB,EAAE,MAAM,CACnC,cAA8D,EAC9D,QAAQ,EACR,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,EAAE,CACzD,CAAC;IACJ,CAAC;IAED,0EAA0E;IAC1E,yCAAyC;IACzC,0EAA0E;IAE1E,mEAAmE;IACnE,YAAY,CAAC,MAA+B;QAC1C,IAAI,MAAM,CAAC,4BAA4B,KAAK,SAAS,EAAE,CAAC;YACtD,IAAI,CAAC,MAAM,CAAC,4BAA4B,GAAG,MAAM,CAAC,4BAA4B,CAAC;YAC/E,IAAI,CAAC,uBAAuB,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,4BAA4B,EAAE,CAAC,CAAC;QAChG,CAAC;QAED,IAAI,MAAM,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,wBAAwB,GAAG,MAAM,CAAC,wBAAwB,CAAC;YACvE,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,wBAAwB,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,MAAM,CAAC,wBAAwB,KAAK,SAAS,EAAE,CAAC;YAClD,IAAI,CAAC,MAAM,CAAC,wBAAwB,GAAG,MAAM,CAAC,wBAAwB,CAAC;YACvE,IAAI,CAAC,mBAAmB,CAAC,YAAY,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,wBAAwB,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,MAAM,CAAC,cAAc,KAAK,SAAS,EAAE,CAAC;YACxC,IAAI,CAAC,MAAM,CAAC,cAAc,GAAG,MAAM,CAAC,cAAc,CAAC;YACnD,IAAI,CAAC,eAAe,CAAC,YAAY,CAAC,EAAE,cAAc,EAAE,MAAM,CAAC,cAAc,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,IAAI,MAAM,CAAC,oBAAoB,KAAK,SAAS,EAAE,CAAC;YAC9C,IAAI,CAAC,MAAM,CAAC,oBAAoB,GAAG,MAAM,CAAC,oBAAoB,CAAC;YAC/D,kCAAkC;YAClC,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBACxB,aAAa,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;gBACnC,IAAI,CAAC,cAAc,GAAG,WAAW,CAAC,GAAG,EAAE;oBACrC,IAAI,CAAC,iBAAiB,EAAE,CAAC;gBAC3B,CAAC,EAAE,MAAM,CAAC,oBAAoB,GAAG,IAAI,CAAC,CAAC;YACzC,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YACjC,IAAI,CAAC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QACvC,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,sBAAsB;IACtB,0EAA0E;IAE1E,+DAA+D;IAC/D,SAAS;QASP,OAAO;YACL,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,OAAO;YAC5B,MAAM,EAAE,EAAE,GAAG,IAAI,CAAC,MAAM,EAAE;YAC1B,KAAK,EAAE;gBACL,mBAAmB,EAAE;oBACnB,cAAc,EAAE,IAAI,CAAC,uBAAuB,CAAC,SAAS,EAAE,CAAC,YAAY;iBACtE;gBACD,eAAe,EAAE;oBACf,cAAc,EAAE,IAAI,CAAC,mBAAmB,CAAC,SAAS,EAAE,CAAC,YAAY;iBAClE;gBACD,WAAW,EAAE;oBACX,eAAe,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,CAAC,YAAY;iBAC/D;aACF;SACF,CAAC;IACJ,CAAC;CACF"}
@@ -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"}