@panguard-ai/threat-cloud 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/audit-logger.d.ts +46 -0
  2. package/dist/audit-logger.d.ts.map +1 -0
  3. package/dist/audit-logger.js +105 -0
  4. package/dist/audit-logger.js.map +1 -0
  5. package/dist/cli.d.ts +9 -0
  6. package/dist/cli.d.ts.map +1 -0
  7. package/dist/cli.js +115 -0
  8. package/dist/cli.js.map +1 -0
  9. package/dist/correlation-engine.d.ts +41 -0
  10. package/dist/correlation-engine.d.ts.map +1 -0
  11. package/dist/correlation-engine.js +313 -0
  12. package/dist/correlation-engine.js.map +1 -0
  13. package/dist/database.d.ts +63 -0
  14. package/dist/database.d.ts.map +1 -0
  15. package/dist/database.js +444 -0
  16. package/dist/database.js.map +1 -0
  17. package/dist/feed-distributor.d.ts +36 -0
  18. package/dist/feed-distributor.d.ts.map +1 -0
  19. package/dist/feed-distributor.js +125 -0
  20. package/dist/feed-distributor.js.map +1 -0
  21. package/dist/index.d.ts +13 -0
  22. package/dist/index.d.ts.map +1 -0
  23. package/dist/index.js +12 -0
  24. package/dist/index.js.map +1 -0
  25. package/dist/ioc-store.d.ts +83 -0
  26. package/dist/ioc-store.d.ts.map +1 -0
  27. package/dist/ioc-store.js +278 -0
  28. package/dist/ioc-store.js.map +1 -0
  29. package/dist/query-handlers.d.ts +40 -0
  30. package/dist/query-handlers.d.ts.map +1 -0
  31. package/dist/query-handlers.js +211 -0
  32. package/dist/query-handlers.js.map +1 -0
  33. package/dist/reputation-engine.d.ts +44 -0
  34. package/dist/reputation-engine.d.ts.map +1 -0
  35. package/dist/reputation-engine.js +169 -0
  36. package/dist/reputation-engine.js.map +1 -0
  37. package/dist/rule-generator.d.ts +47 -0
  38. package/dist/rule-generator.d.ts.map +1 -0
  39. package/dist/rule-generator.js +238 -0
  40. package/dist/rule-generator.js.map +1 -0
  41. package/dist/scheduler.d.ts +52 -0
  42. package/dist/scheduler.d.ts.map +1 -0
  43. package/dist/scheduler.js +143 -0
  44. package/dist/scheduler.js.map +1 -0
  45. package/dist/server.d.ts +99 -0
  46. package/dist/server.d.ts.map +1 -0
  47. package/dist/server.js +809 -0
  48. package/dist/server.js.map +1 -0
  49. package/dist/sighting-store.d.ts +61 -0
  50. package/dist/sighting-store.d.ts.map +1 -0
  51. package/dist/sighting-store.js +191 -0
  52. package/dist/sighting-store.js.map +1 -0
  53. package/dist/types.d.ts +352 -0
  54. package/dist/types.d.ts.map +1 -0
  55. package/dist/types.js +6 -0
  56. package/dist/types.js.map +1 -0
  57. package/package.json +37 -0
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Feed Distributor
3
+ * 情報分發模組
4
+ *
5
+ * Generates blocklists, IoC feeds, and agent update packages.
6
+ *
7
+ * @module @panguard-ai/threat-cloud/feed-distributor
8
+ */
9
+ export class FeedDistributor {
10
+ db;
11
+ constructor(db) {
12
+ this.db = db;
13
+ }
14
+ /**
15
+ * Generate IP blocklist as plain text (one IP per line).
16
+ * Only includes redistributable IoCs to comply with feed licenses.
17
+ * 產生 IP 封鎖清單(僅包含可轉散佈的 IoC,遵守授權)
18
+ */
19
+ getIPBlocklist(minReputation = 70) {
20
+ const rows = this.db
21
+ .prepare(`SELECT normalized_value
22
+ FROM iocs
23
+ WHERE type = 'ip' AND status = 'active' AND reputation_score >= ?
24
+ AND (json_extract(metadata, '$.redistributable') != 'false'
25
+ OR json_extract(metadata, '$.redistributable') IS NULL
26
+ OR source NOT LIKE 'feed:%')
27
+ ORDER BY reputation_score DESC`)
28
+ .all(minReputation);
29
+ return rows.map((r) => r.normalized_value).join('\n');
30
+ }
31
+ /**
32
+ * Generate domain blocklist as plain text.
33
+ * 產生 Domain 封鎖清單
34
+ */
35
+ getDomainBlocklist(minReputation = 70) {
36
+ const rows = this.db
37
+ .prepare(`SELECT normalized_value
38
+ FROM iocs
39
+ WHERE type = 'domain' AND status = 'active' AND reputation_score >= ?
40
+ AND (json_extract(metadata, '$.redistributable') != 'false'
41
+ OR json_extract(metadata, '$.redistributable') IS NULL
42
+ OR source NOT LIKE 'feed:%')
43
+ ORDER BY reputation_score DESC`)
44
+ .all(minReputation);
45
+ return rows.map((r) => r.normalized_value).join('\n');
46
+ }
47
+ /**
48
+ * Generate JSON IoC feed.
49
+ * 產生 JSON IoC feed
50
+ */
51
+ getIoCFeed(minReputation = 50, limit = 1000, since) {
52
+ const conditions = ["status = 'active'", 'reputation_score >= ?'];
53
+ const params = [minReputation];
54
+ if (since) {
55
+ conditions.push('last_seen > ?');
56
+ params.push(since);
57
+ }
58
+ const safeLimit = Math.min(Math.max(1, limit), 10000);
59
+ const where = conditions.join(' AND ');
60
+ const rows = this.db
61
+ .prepare(`SELECT type, normalized_value, threat_type, reputation_score, confidence, last_seen, tags
62
+ FROM iocs
63
+ WHERE ${where}
64
+ ORDER BY reputation_score DESC
65
+ LIMIT ?`)
66
+ .all(...params, safeLimit);
67
+ const entries = rows.map((r) => ({
68
+ type: r.type,
69
+ value: r.normalized_value,
70
+ threatType: r.threat_type,
71
+ reputation: r.reputation_score,
72
+ confidence: r.confidence,
73
+ lastSeen: r.last_seen,
74
+ tags: JSON.parse(r.tags),
75
+ }));
76
+ return {
77
+ generatedAt: new Date().toISOString(),
78
+ totalEntries: entries.length,
79
+ entries,
80
+ };
81
+ }
82
+ /**
83
+ * Generate agent update package (rules + IoCs since a given timestamp).
84
+ * 產生 Agent 更新包
85
+ */
86
+ getAgentUpdate(since) {
87
+ const sinceDate = since ?? new Date(Date.now() - 24 * 60 * 60 * 1000).toISOString();
88
+ // Fetch new rules
89
+ const rules = this.db
90
+ .prepare(`SELECT rule_id as ruleId, rule_content as ruleContent, published_at as publishedAt, source
91
+ FROM rules
92
+ WHERE published_at > ?
93
+ ORDER BY published_at ASC`)
94
+ .all(sinceDate);
95
+ // Fetch high-reputation IoCs updated since
96
+ const iocRows = this.db
97
+ .prepare(`SELECT type, normalized_value, threat_type, reputation_score, confidence, last_seen, tags
98
+ FROM iocs
99
+ WHERE status = 'active' AND reputation_score >= 60 AND updated_at > ?
100
+ ORDER BY reputation_score DESC
101
+ LIMIT 500`)
102
+ .all(sinceDate);
103
+ const iocs = iocRows.map((r) => ({
104
+ type: r.type,
105
+ value: r.normalized_value,
106
+ threatType: r.threat_type,
107
+ reputation: r.reputation_score,
108
+ confidence: r.confidence,
109
+ lastSeen: r.last_seen,
110
+ tags: JSON.parse(r.tags),
111
+ }));
112
+ const totalActiveIoCs = this.db.prepare("SELECT COUNT(*) as count FROM iocs WHERE status = 'active'").get().count;
113
+ return {
114
+ generatedAt: new Date().toISOString(),
115
+ rules,
116
+ iocs,
117
+ stats: {
118
+ newRules: rules.length,
119
+ newIoCs: iocs.length,
120
+ totalActiveIoCs,
121
+ },
122
+ };
123
+ }
124
+ }
125
+ //# sourceMappingURL=feed-distributor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feed-distributor.js","sourceRoot":"","sources":["../src/feed-distributor.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { ThreatCloudServer } from './server.js';
2
+ export { ThreatCloudDB } from './database.js';
3
+ export { IoCStore } from './ioc-store.js';
4
+ export { ReputationEngine } from './reputation-engine.js';
5
+ export { CorrelationEngine } from './correlation-engine.js';
6
+ export { RuleGenerator } from './rule-generator.js';
7
+ export { QueryHandlers } from './query-handlers.js';
8
+ export { FeedDistributor } from './feed-distributor.js';
9
+ export { SightingStore } from './sighting-store.js';
10
+ export { AuditLogger } from './audit-logger.js';
11
+ export { Scheduler } from './scheduler.js';
12
+ export type { AnonymizedThreatData, ThreatCloudRule, ThreatStats, ServerConfig, ApiResponse, IoCType, IoCStatus, IoCRecord, IoCInput, IoCLookupResult, TrapIntelligencePayload, EnrichedThreatEvent, PaginationParams, PaginatedResponse, ReputationConfig, CorrelationConfig, Campaign, CampaignScanResult, CampaignStats, DetectedPattern, RuleGenerationResult, RuleGeneratorConfig, TimeSeriesPoint, GeoDistributionEntry, TrendEntry, MitreHeatmapEntry, EnhancedStats, IoCFeedEntry, IoCFeedResponse, AgentUpdatePackage, SchedulerConfig, SourceReliability, SightingType, SightingInput, SightingRecord, AuditAction, AuditLogEntry, AuditLogQuery, FeedLicense, FeedSourceConfig, } from './types.js';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EACV,oBAAoB,EACpB,eAAe,EACf,WAAW,EACX,YAAY,EACZ,WAAW,EACX,OAAO,EACP,SAAS,EACT,SAAS,EACT,QAAQ,EACR,eAAe,EACf,uBAAuB,EACvB,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,QAAQ,EACR,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACb,YAAY,EACZ,eAAe,EACf,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,WAAW,EACX,aAAa,EACb,aAAa,EACb,WAAW,EACX,gBAAgB,GACjB,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ export { ThreatCloudServer } from './server.js';
2
+ export { ThreatCloudDB } from './database.js';
3
+ export { IoCStore } from './ioc-store.js';
4
+ export { ReputationEngine } from './reputation-engine.js';
5
+ export { CorrelationEngine } from './correlation-engine.js';
6
+ export { RuleGenerator } from './rule-generator.js';
7
+ export { QueryHandlers } from './query-handlers.js';
8
+ export { FeedDistributor } from './feed-distributor.js';
9
+ export { SightingStore } from './sighting-store.js';
10
+ export { AuditLogger } from './audit-logger.js';
11
+ export { Scheduler } from './scheduler.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * IoC (Indicator of Compromise) Store
3
+ * IoC(入侵指標)儲存模組
4
+ *
5
+ * Handles CRUD, normalization, deduplication, and sighting-merge for IoCs.
6
+ *
7
+ * @module @panguard-ai/threat-cloud/ioc-store
8
+ */
9
+ import type Database from 'better-sqlite3';
10
+ import type { IoCType, IoCStatus, IoCRecord, IoCInput, IoCLookupResult, PaginationParams, PaginatedResponse } from './types.js';
11
+ export declare class IoCStore {
12
+ private readonly db;
13
+ constructor(db: Database.Database);
14
+ /**
15
+ * Normalize IoC value for deduplication.
16
+ * 正規化 IoC 值以便去重
17
+ */
18
+ normalizeValue(type: IoCType, value: string): string;
19
+ /**
20
+ * Auto-detect IoC type from value / 自動偵測 IoC 類型
21
+ */
22
+ detectType(value: string): IoCType;
23
+ /**
24
+ * Upsert an IoC: insert if new, merge sighting if existing.
25
+ * Upsert IoC:新建或合併觀測
26
+ */
27
+ upsertIoC(input: IoCInput): IoCRecord;
28
+ /**
29
+ * Lookup a single IoC by type+value / 以 type+value 查詢單一 IoC
30
+ */
31
+ lookupIoC(type: IoCType, value: string): IoCRecord | null;
32
+ /**
33
+ * Lookup IoC with related threat count / 查詢 IoC 含相關威脅數
34
+ */
35
+ lookupIoCWithContext(type: IoCType, value: string, countThreats: (ip: string) => number): IoCLookupResult;
36
+ /**
37
+ * Get IoC by ID / 以 ID 取得 IoC
38
+ */
39
+ getIoCById(id: number): IoCRecord | null;
40
+ /**
41
+ * Get active IoCs by type with minimum reputation / 取得特定類型的活躍 IoC
42
+ */
43
+ getActiveIoCsByType(type: IoCType, minReputation: number, limit: number): IoCRecord[];
44
+ /**
45
+ * Search IoCs with filters and pagination / 以篩選條件搜尋 IoC
46
+ */
47
+ searchIoCs(filters: {
48
+ type?: IoCType;
49
+ source?: string;
50
+ minReputation?: number;
51
+ status?: IoCStatus;
52
+ since?: string;
53
+ search?: string;
54
+ }, pagination: PaginationParams): PaginatedResponse<IoCRecord>;
55
+ /**
56
+ * Batch update reputation scores / 批次更新信譽分數
57
+ */
58
+ batchUpdateReputation(updates: Array<{
59
+ id: number;
60
+ reputationScore: number;
61
+ }>): void;
62
+ /**
63
+ * Expire stale IoCs / 過期未活躍的 IoC
64
+ */
65
+ expireStaleIoCs(olderThan: string): number;
66
+ /**
67
+ * Delete expired IoCs beyond retention / 刪除超齡的已過期 IoC
68
+ */
69
+ purgeExpiredIoCs(olderThan: string): number;
70
+ /**
71
+ * Get IoC counts by type / 取得各類型 IoC 數量
72
+ */
73
+ getIoCCountsByType(): Record<string, number>;
74
+ /**
75
+ * Get top malicious IoCs / 取得最高威脅度 IoC
76
+ */
77
+ getTopMaliciousIoCs(limit: number): IoCRecord[];
78
+ /**
79
+ * Get total active IoC count / 取得活躍 IoC 總數
80
+ */
81
+ getTotalActiveCount(): number;
82
+ }
83
+ //# sourceMappingURL=ioc-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ioc-store.d.ts","sourceRoot":"","sources":["../src/ioc-store.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EACV,OAAO,EACP,SAAS,EACT,SAAS,EACT,QAAQ,EACR,eAAe,EACf,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AA4CpB,qBAAa,QAAQ;IACP,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAMlD;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM;IAuBpD;;OAEG;IACH,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO;IAsBlC;;;OAGG;IACH,SAAS,CAAC,KAAK,EAAE,QAAQ,GAAG,SAAS;IA0DrC;;OAEG;IACH,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAQzD;;OAEG;IACH,oBAAoB,CAClB,IAAI,EAAE,OAAO,EACb,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,GACnC,eAAe;IASlB;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI;IAKxC;;OAEG;IACH,mBAAmB,CAAC,IAAI,EAAE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE;IAYrF;;OAEG;IACH,UAAU,CACR,OAAO,EAAE;QACP,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,aAAa,CAAC,EAAE,MAAM,CAAC;QACvB,MAAM,CAAC,EAAE,SAAS,CAAC;QACnB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,MAAM,CAAC;KACjB,EACD,UAAU,EAAE,gBAAgB,GAC3B,iBAAiB,CAAC,SAAS,CAAC;IAuD/B;;OAEG;IACH,qBAAqB,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,eAAe,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI;IAYpF;;OAEG;IACH,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAS1C;;OAEG;IACH,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM;IAO3C;;OAEG;IACH,kBAAkB,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;IAW5C;;OAEG;IACH,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,EAAE;IAO/C;;OAEG;IACH,mBAAmB,IAAI,MAAM;CAO9B"}
@@ -0,0 +1,278 @@
1
+ /**
2
+ * IoC (Indicator of Compromise) Store
3
+ * IoC(入侵指標)儲存模組
4
+ *
5
+ * Handles CRUD, normalization, deduplication, and sighting-merge for IoCs.
6
+ *
7
+ * @module @panguard-ai/threat-cloud/ioc-store
8
+ */
9
+ /** Convert DB row to IoCRecord / 將 DB 列轉換為 IoCRecord */
10
+ function rowToRecord(row) {
11
+ return {
12
+ id: row.id,
13
+ type: row.type,
14
+ value: row.value,
15
+ normalizedValue: row.normalized_value,
16
+ threatType: row.threat_type,
17
+ source: row.source,
18
+ confidence: row.confidence,
19
+ reputationScore: row.reputation_score,
20
+ firstSeen: row.first_seen,
21
+ lastSeen: row.last_seen,
22
+ sightings: row.sightings,
23
+ status: row.status,
24
+ tags: JSON.parse(row.tags),
25
+ metadata: JSON.parse(row.metadata),
26
+ createdAt: row.created_at,
27
+ updatedAt: row.updated_at,
28
+ };
29
+ }
30
+ export class IoCStore {
31
+ db;
32
+ constructor(db) {
33
+ this.db = db;
34
+ }
35
+ // -------------------------------------------------------------------------
36
+ // Normalization / 正規化
37
+ // -------------------------------------------------------------------------
38
+ /**
39
+ * Normalize IoC value for deduplication.
40
+ * 正規化 IoC 值以便去重
41
+ */
42
+ normalizeValue(type, value) {
43
+ const trimmed = value.trim();
44
+ switch (type) {
45
+ case 'ip': {
46
+ // Strip port if present (e.g., "1.2.3.4:8080" -> "1.2.3.4")
47
+ const noPort = trimmed.replace(/:\d+$/, '');
48
+ return noPort.toLowerCase();
49
+ }
50
+ case 'domain':
51
+ // Lowercase, remove trailing dot
52
+ return trimmed.toLowerCase().replace(/\.$/, '');
53
+ case 'url':
54
+ // Lowercase scheme+host, strip trailing slash
55
+ return trimmed.toLowerCase().replace(/\/+$/, '');
56
+ case 'hash_md5':
57
+ case 'hash_sha1':
58
+ case 'hash_sha256':
59
+ return trimmed.toLowerCase();
60
+ default:
61
+ return trimmed.toLowerCase();
62
+ }
63
+ }
64
+ /**
65
+ * Auto-detect IoC type from value / 自動偵測 IoC 類型
66
+ */
67
+ detectType(value) {
68
+ const v = value.trim();
69
+ // IPv4
70
+ if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(:\d+)?$/.test(v))
71
+ return 'ip';
72
+ // IPv6
73
+ if (v.includes(':') && /^[0-9a-fA-F:]+$/.test(v))
74
+ return 'ip';
75
+ // URL
76
+ if (/^https?:\/\//i.test(v))
77
+ return 'url';
78
+ // SHA-256
79
+ if (/^[a-fA-F0-9]{64}$/.test(v))
80
+ return 'hash_sha256';
81
+ // SHA-1
82
+ if (/^[a-fA-F0-9]{40}$/.test(v))
83
+ return 'hash_sha1';
84
+ // MD5
85
+ if (/^[a-fA-F0-9]{32}$/.test(v))
86
+ return 'hash_md5';
87
+ // Default to domain
88
+ return 'domain';
89
+ }
90
+ // -------------------------------------------------------------------------
91
+ // CRUD / 資料操作
92
+ // -------------------------------------------------------------------------
93
+ /**
94
+ * Upsert an IoC: insert if new, merge sighting if existing.
95
+ * Upsert IoC:新建或合併觀測
96
+ */
97
+ upsertIoC(input) {
98
+ const normalized = this.normalizeValue(input.type, input.value);
99
+ const now = new Date().toISOString();
100
+ const tags = input.tags ?? [];
101
+ const metadata = input.metadata ?? {};
102
+ // Try to find existing
103
+ const existing = this.db
104
+ .prepare('SELECT * FROM iocs WHERE type = ? AND normalized_value = ?')
105
+ .get(input.type, normalized);
106
+ if (existing) {
107
+ // Merge: increment sightings, update last_seen, update confidence, merge tags
108
+ const existingTags = JSON.parse(existing.tags);
109
+ const mergedTags = [...new Set([...existingTags, ...tags])];
110
+ const newConfidence = Math.max(existing.confidence, input.confidence);
111
+ const newLastSeen = now > existing.last_seen ? now : existing.last_seen;
112
+ this.db
113
+ .prepare(`UPDATE iocs SET
114
+ sightings = sightings + 1,
115
+ last_seen = ?,
116
+ confidence = ?,
117
+ tags = ?,
118
+ status = CASE WHEN status = 'expired' THEN 'active' ELSE status END,
119
+ updated_at = datetime('now')
120
+ WHERE id = ?`)
121
+ .run(newLastSeen, newConfidence, JSON.stringify(mergedTags), existing.id);
122
+ return this.getIoCById(existing.id);
123
+ }
124
+ // Insert new
125
+ const result = this.db
126
+ .prepare(`INSERT INTO iocs
127
+ (type, value, normalized_value, threat_type, source, confidence,
128
+ reputation_score, first_seen, last_seen, tags, metadata)
129
+ VALUES (?, ?, ?, ?, ?, ?, 50, ?, ?, ?, ?)`)
130
+ .run(input.type, input.value, normalized, input.threatType, input.source, input.confidence, now, now, JSON.stringify(tags), JSON.stringify(metadata));
131
+ return this.getIoCById(Number(result.lastInsertRowid));
132
+ }
133
+ /**
134
+ * Lookup a single IoC by type+value / 以 type+value 查詢單一 IoC
135
+ */
136
+ lookupIoC(type, value) {
137
+ const normalized = this.normalizeValue(type, value);
138
+ const row = this.db
139
+ .prepare('SELECT * FROM iocs WHERE type = ? AND normalized_value = ?')
140
+ .get(type, normalized);
141
+ return row ? rowToRecord(row) : null;
142
+ }
143
+ /**
144
+ * Lookup IoC with related threat count / 查詢 IoC 含相關威脅數
145
+ */
146
+ lookupIoCWithContext(type, value, countThreats) {
147
+ const ioc = this.lookupIoC(type, value);
148
+ if (!ioc) {
149
+ return { found: false, relatedThreats: 0 };
150
+ }
151
+ const relatedThreats = type === 'ip' ? countThreats(ioc.normalizedValue) : 0;
152
+ return { found: true, ioc, relatedThreats };
153
+ }
154
+ /**
155
+ * Get IoC by ID / 以 ID 取得 IoC
156
+ */
157
+ getIoCById(id) {
158
+ const row = this.db.prepare('SELECT * FROM iocs WHERE id = ?').get(id);
159
+ return row ? rowToRecord(row) : null;
160
+ }
161
+ /**
162
+ * Get active IoCs by type with minimum reputation / 取得特定類型的活躍 IoC
163
+ */
164
+ getActiveIoCsByType(type, minReputation, limit) {
165
+ const rows = this.db
166
+ .prepare(`SELECT * FROM iocs
167
+ WHERE type = ? AND status = 'active' AND reputation_score >= ?
168
+ ORDER BY reputation_score DESC
169
+ LIMIT ?`)
170
+ .all(type, minReputation, limit);
171
+ return rows.map(rowToRecord);
172
+ }
173
+ /**
174
+ * Search IoCs with filters and pagination / 以篩選條件搜尋 IoC
175
+ */
176
+ searchIoCs(filters, pagination) {
177
+ const conditions = [];
178
+ const params = [];
179
+ if (filters.type) {
180
+ conditions.push('type = ?');
181
+ params.push(filters.type);
182
+ }
183
+ if (filters.source) {
184
+ conditions.push('source = ?');
185
+ params.push(filters.source);
186
+ }
187
+ if (filters.minReputation !== undefined) {
188
+ conditions.push('reputation_score >= ?');
189
+ params.push(filters.minReputation);
190
+ }
191
+ if (filters.status) {
192
+ conditions.push('status = ?');
193
+ params.push(filters.status);
194
+ }
195
+ if (filters.since) {
196
+ conditions.push('updated_at > ?');
197
+ params.push(filters.since);
198
+ }
199
+ if (filters.search) {
200
+ conditions.push('normalized_value LIKE ?');
201
+ params.push(`%${filters.search}%`);
202
+ }
203
+ const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
204
+ const safePage = Math.max(1, pagination.page);
205
+ const safeLimit = Math.min(Math.max(1, pagination.limit), 1000);
206
+ const offset = (safePage - 1) * safeLimit;
207
+ const total = this.db.prepare(`SELECT COUNT(*) as count FROM iocs ${where}`).get(...params).count;
208
+ const rows = this.db
209
+ .prepare(`SELECT * FROM iocs ${where} ORDER BY reputation_score DESC, last_seen DESC LIMIT ? OFFSET ?`)
210
+ .all(...params, safeLimit, offset);
211
+ return {
212
+ items: rows.map(rowToRecord),
213
+ total,
214
+ page: safePage,
215
+ limit: safeLimit,
216
+ hasMore: offset + safeLimit < total,
217
+ };
218
+ }
219
+ /**
220
+ * Batch update reputation scores / 批次更新信譽分數
221
+ */
222
+ batchUpdateReputation(updates) {
223
+ const stmt = this.db.prepare("UPDATE iocs SET reputation_score = ?, updated_at = datetime('now') WHERE id = ?");
224
+ const updateAll = this.db.transaction((items) => {
225
+ for (const u of items) {
226
+ stmt.run(Math.max(0, Math.min(100, Math.round(u.reputationScore))), u.id);
227
+ }
228
+ });
229
+ updateAll(updates);
230
+ }
231
+ /**
232
+ * Expire stale IoCs / 過期未活躍的 IoC
233
+ */
234
+ expireStaleIoCs(olderThan) {
235
+ const result = this.db
236
+ .prepare("UPDATE iocs SET status = 'expired', updated_at = datetime('now') WHERE status = 'active' AND last_seen < ?")
237
+ .run(olderThan);
238
+ return result.changes;
239
+ }
240
+ /**
241
+ * Delete expired IoCs beyond retention / 刪除超齡的已過期 IoC
242
+ */
243
+ purgeExpiredIoCs(olderThan) {
244
+ const result = this.db
245
+ .prepare("DELETE FROM iocs WHERE status = 'expired' AND updated_at < ?")
246
+ .run(olderThan);
247
+ return result.changes;
248
+ }
249
+ /**
250
+ * Get IoC counts by type / 取得各類型 IoC 數量
251
+ */
252
+ getIoCCountsByType() {
253
+ const rows = this.db
254
+ .prepare("SELECT type, COUNT(*) as count FROM iocs WHERE status = 'active' GROUP BY type")
255
+ .all();
256
+ const result = {};
257
+ for (const r of rows) {
258
+ result[r.type] = r.count;
259
+ }
260
+ return result;
261
+ }
262
+ /**
263
+ * Get top malicious IoCs / 取得最高威脅度 IoC
264
+ */
265
+ getTopMaliciousIoCs(limit) {
266
+ const rows = this.db
267
+ .prepare("SELECT * FROM iocs WHERE status = 'active' ORDER BY reputation_score DESC LIMIT ?")
268
+ .all(limit);
269
+ return rows.map(rowToRecord);
270
+ }
271
+ /**
272
+ * Get total active IoC count / 取得活躍 IoC 總數
273
+ */
274
+ getTotalActiveCount() {
275
+ return this.db.prepare("SELECT COUNT(*) as count FROM iocs WHERE status = 'active'").get().count;
276
+ }
277
+ }
278
+ //# sourceMappingURL=ioc-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ioc-store.js","sourceRoot":"","sources":["../src/ioc-store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Query Handlers for advanced analytics
3
+ * 進階分析查詢處理器
4
+ *
5
+ * Provides timeseries, geo distribution, trends, and MITRE heatmap queries.
6
+ *
7
+ * @module @panguard-ai/threat-cloud/query-handlers
8
+ */
9
+ import type Database from 'better-sqlite3';
10
+ import type { TimeSeriesPoint, GeoDistributionEntry, TrendEntry, MitreHeatmapEntry, EnhancedStats } from './types.js';
11
+ export declare class QueryHandlers {
12
+ private readonly db;
13
+ constructor(db: Database.Database);
14
+ /**
15
+ * Time-series query: event counts grouped by time bucket.
16
+ * 時間序列查詢:依時間桶分組的事件計數
17
+ */
18
+ getTimeSeries(granularity?: 'hour' | 'day' | 'week', since?: string, attackType?: string): TimeSeriesPoint[];
19
+ /**
20
+ * Geographic distribution query.
21
+ * 地理分佈查詢
22
+ */
23
+ getGeoDistribution(since?: string): GeoDistributionEntry[];
24
+ /**
25
+ * Trend analysis: compare current period with previous period.
26
+ * 趨勢分析:比較當前與前一期間
27
+ */
28
+ getTrends(periodDays?: number): TrendEntry[];
29
+ /**
30
+ * MITRE ATT&CK technique heatmap.
31
+ * MITRE ATT&CK 技術熱力圖
32
+ */
33
+ getMitreHeatmap(since?: string): MitreHeatmapEntry[];
34
+ /**
35
+ * Enhanced stats combining all data sources.
36
+ * 增強統計:整合所有資料來源
37
+ */
38
+ getEnhancedStats(): EnhancedStats;
39
+ }
40
+ //# sourceMappingURL=query-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"query-handlers.d.ts","sourceRoot":"","sources":["../src/query-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAC3C,OAAO,KAAK,EACV,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,aAAa,EACd,MAAM,YAAY,CAAC;AAEpB,qBAAa,aAAa;IACZ,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,QAAQ,CAAC,QAAQ;IAElD;;;OAGG;IACH,aAAa,CACX,WAAW,GAAE,MAAM,GAAG,KAAK,GAAG,MAAc,EAC5C,KAAK,CAAC,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,MAAM,GAClB,eAAe,EAAE;IAkCpB;;;OAGG;IACH,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,oBAAoB,EAAE;IAkC1D;;;OAGG;IACH,SAAS,CAAC,UAAU,GAAE,MAAU,GAAG,UAAU,EAAE;IAmD/C;;;OAGG;IACH,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE;IAiCpD;;;OAGG;IACH,gBAAgB,IAAI,aAAa;CAsGlC"}