@grc-claw/continuous-trust-engine 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +145 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +291 -0
- package/dist/index.js.map +1 -0
- package/package.json +19 -0
- package/src/index.ts +377 -0
- package/tsconfig.json +9 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContinuousTrustEngine - Real-time trust scoring for compliance posture
|
|
3
|
+
*
|
|
4
|
+
* Continuously evaluates compliance posture, evidence quality, agent behavior,
|
|
5
|
+
* and organizational trust signals to produce a dynamic trust score.
|
|
6
|
+
*
|
|
7
|
+
* This engine goes beyond static compliance checks by incorporating:
|
|
8
|
+
* - Real-time evidence freshness scoring
|
|
9
|
+
* - Agent behavioral trust signals
|
|
10
|
+
* - Control effectiveness metrics
|
|
11
|
+
* - Risk-adjusted trust calculations
|
|
12
|
+
* - Trust decay over time
|
|
13
|
+
* - Trust threshold alerts
|
|
14
|
+
*/
|
|
15
|
+
export interface TrustSignal {
|
|
16
|
+
id: string;
|
|
17
|
+
type: 'evidence' | 'control' | 'agent' | 'risk' | 'behavior' | 'external';
|
|
18
|
+
name: string;
|
|
19
|
+
value: number;
|
|
20
|
+
weight: number;
|
|
21
|
+
timestamp: Date;
|
|
22
|
+
metadata: Record<string, unknown>;
|
|
23
|
+
}
|
|
24
|
+
export interface TrustScore {
|
|
25
|
+
overall: number;
|
|
26
|
+
breakdown: {
|
|
27
|
+
evidence: number;
|
|
28
|
+
control: number;
|
|
29
|
+
agent: number;
|
|
30
|
+
risk: number;
|
|
31
|
+
behavior: number;
|
|
32
|
+
external: number;
|
|
33
|
+
};
|
|
34
|
+
trend: 'improving' | 'stable' | 'declining';
|
|
35
|
+
trendDelta: number;
|
|
36
|
+
lastUpdated: Date;
|
|
37
|
+
nextUpdate: Date;
|
|
38
|
+
alerts: TrustAlert[];
|
|
39
|
+
}
|
|
40
|
+
export interface TrustAlert {
|
|
41
|
+
id: string;
|
|
42
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
43
|
+
type: string;
|
|
44
|
+
message: string;
|
|
45
|
+
threshold: number;
|
|
46
|
+
currentValue: number;
|
|
47
|
+
timestamp: Date;
|
|
48
|
+
acknowledged: boolean;
|
|
49
|
+
}
|
|
50
|
+
export interface TrustThreshold {
|
|
51
|
+
metric: string;
|
|
52
|
+
critical: number;
|
|
53
|
+
high: number;
|
|
54
|
+
medium: number;
|
|
55
|
+
low: number;
|
|
56
|
+
}
|
|
57
|
+
export interface TrustHistoryEntry {
|
|
58
|
+
timestamp: Date;
|
|
59
|
+
score: TrustScore;
|
|
60
|
+
signals: TrustSignal[];
|
|
61
|
+
}
|
|
62
|
+
export declare class ContinuousTrustEngine {
|
|
63
|
+
private readonly options;
|
|
64
|
+
private signals;
|
|
65
|
+
private history;
|
|
66
|
+
private thresholds;
|
|
67
|
+
private alerts;
|
|
68
|
+
private updateInterval;
|
|
69
|
+
private listeners;
|
|
70
|
+
constructor(options?: {
|
|
71
|
+
updateIntervalMs?: number;
|
|
72
|
+
historyRetentionDays?: number;
|
|
73
|
+
maxAlerts?: number;
|
|
74
|
+
autoAcknowledgeAfterMs?: number;
|
|
75
|
+
});
|
|
76
|
+
/**
|
|
77
|
+
* Start continuous trust monitoring
|
|
78
|
+
*/
|
|
79
|
+
start(): void;
|
|
80
|
+
/**
|
|
81
|
+
* Stop continuous trust monitoring
|
|
82
|
+
*/
|
|
83
|
+
stop(): void;
|
|
84
|
+
/**
|
|
85
|
+
* Register a trust signal
|
|
86
|
+
*/
|
|
87
|
+
registerSignal(signal: TrustSignal): void;
|
|
88
|
+
/**
|
|
89
|
+
* Update an existing trust signal
|
|
90
|
+
*/
|
|
91
|
+
updateSignal(id: string, updates: Partial<TrustSignal>): void;
|
|
92
|
+
/**
|
|
93
|
+
* Remove a trust signal
|
|
94
|
+
*/
|
|
95
|
+
removeSignal(id: string): void;
|
|
96
|
+
/**
|
|
97
|
+
* Get current trust score
|
|
98
|
+
*/
|
|
99
|
+
getScore(): TrustScore;
|
|
100
|
+
/**
|
|
101
|
+
* Get trust history
|
|
102
|
+
*/
|
|
103
|
+
getHistory(hours?: number): TrustHistoryEntry[];
|
|
104
|
+
/**
|
|
105
|
+
* Get active alerts
|
|
106
|
+
*/
|
|
107
|
+
getAlerts(acknowledged?: boolean): TrustAlert[];
|
|
108
|
+
/**
|
|
109
|
+
* Acknowledge an alert
|
|
110
|
+
*/
|
|
111
|
+
acknowledgeAlert(alertId: string): void;
|
|
112
|
+
/**
|
|
113
|
+
* Subscribe to trust score updates
|
|
114
|
+
*/
|
|
115
|
+
subscribe(listener: (score: TrustScore) => void): () => void;
|
|
116
|
+
/**
|
|
117
|
+
* Set custom thresholds
|
|
118
|
+
*/
|
|
119
|
+
setThresholds(thresholds: TrustThreshold[]): void;
|
|
120
|
+
/**
|
|
121
|
+
* Calculate trust score from all signals
|
|
122
|
+
*/
|
|
123
|
+
private calculateScore;
|
|
124
|
+
/**
|
|
125
|
+
* Calculate score and notify listeners
|
|
126
|
+
*/
|
|
127
|
+
private calculateAndNotify;
|
|
128
|
+
/**
|
|
129
|
+
* Evaluate thresholds and create alerts
|
|
130
|
+
*/
|
|
131
|
+
private evaluateThresholds;
|
|
132
|
+
/**
|
|
133
|
+
* Get metric value from score
|
|
134
|
+
*/
|
|
135
|
+
private getMetricValue;
|
|
136
|
+
/**
|
|
137
|
+
* Create a new alert
|
|
138
|
+
*/
|
|
139
|
+
private createAlert;
|
|
140
|
+
/**
|
|
141
|
+
* Initialize default thresholds
|
|
142
|
+
*/
|
|
143
|
+
private initializeDefaultThresholds;
|
|
144
|
+
}
|
|
145
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,GAAG,UAAU,CAAC;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,IAAI,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE;QACT,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,KAAK,EAAE,WAAW,GAAG,QAAQ,GAAG,WAAW,CAAC;IAC5C,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,IAAI,CAAC;IAClB,UAAU,EAAE,IAAI,CAAC;IACjB,MAAM,EAAE,UAAU,EAAE,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;CACb;AAED,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,UAAU,CAAC;IAClB,OAAO,EAAE,WAAW,EAAE,CAAC;CACxB;AAED,qBAAa,qBAAqB;IAS9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IAR1B,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,OAAO,CAA2B;IAC1C,OAAO,CAAC,UAAU,CAAwB;IAC1C,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,SAAS,CAAuC;gBAGrC,OAAO,GAAE;QACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,oBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,sBAAsB,CAAC,EAAE,MAAM,CAAC;KAC5B;IAaR;;OAEG;IACH,KAAK,IAAI,IAAI;IAab;;OAEG;IACH,IAAI,IAAI,IAAI;IAOZ;;OAEG;IACH,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI;IAKzC;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,IAAI;IAQ7D;;OAEG;IACH,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI;IAI9B;;OAEG;IACH,QAAQ,IAAI,UAAU;IAItB;;OAEG;IACH,UAAU,CAAC,KAAK,GAAE,MAAW,GAAG,iBAAiB,EAAE;IAKnD;;OAEG;IACH,SAAS,CAAC,YAAY,GAAE,OAAe,GAAG,UAAU,EAAE;IAItD;;OAEG;IACH,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI;IAOvC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,MAAM,IAAI;IAO5D;;OAEG;IACH,aAAa,CAAC,UAAU,EAAE,cAAc,EAAE,GAAG,IAAI;IAIjD;;OAEG;IACH,OAAO,CAAC,cAAc;IAqEtB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAkC1B;;OAEG;IACH,OAAO,CAAC,cAAc;IAatB;;OAEG;IACH,OAAO,CAAC,WAAW;IAmBnB;;OAEG;IACH,OAAO,CAAC,2BAA2B;CASpC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ContinuousTrustEngine - Real-time trust scoring for compliance posture
|
|
4
|
+
*
|
|
5
|
+
* Continuously evaluates compliance posture, evidence quality, agent behavior,
|
|
6
|
+
* and organizational trust signals to produce a dynamic trust score.
|
|
7
|
+
*
|
|
8
|
+
* This engine goes beyond static compliance checks by incorporating:
|
|
9
|
+
* - Real-time evidence freshness scoring
|
|
10
|
+
* - Agent behavioral trust signals
|
|
11
|
+
* - Control effectiveness metrics
|
|
12
|
+
* - Risk-adjusted trust calculations
|
|
13
|
+
* - Trust decay over time
|
|
14
|
+
* - Trust threshold alerts
|
|
15
|
+
*/
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.ContinuousTrustEngine = void 0;
|
|
18
|
+
class ContinuousTrustEngine {
|
|
19
|
+
options;
|
|
20
|
+
signals = new Map();
|
|
21
|
+
history = [];
|
|
22
|
+
thresholds = [];
|
|
23
|
+
alerts = [];
|
|
24
|
+
updateInterval = null;
|
|
25
|
+
listeners = [];
|
|
26
|
+
constructor(options = {}) {
|
|
27
|
+
this.options = options;
|
|
28
|
+
this.options = {
|
|
29
|
+
updateIntervalMs: 60000, // 1 minute
|
|
30
|
+
historyRetentionDays: 90,
|
|
31
|
+
maxAlerts: 1000,
|
|
32
|
+
autoAcknowledgeAfterMs: 86400000, // 24 hours
|
|
33
|
+
...options
|
|
34
|
+
};
|
|
35
|
+
this.initializeDefaultThresholds();
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Start continuous trust monitoring
|
|
39
|
+
*/
|
|
40
|
+
start() {
|
|
41
|
+
if (this.updateInterval) {
|
|
42
|
+
return; // Already running
|
|
43
|
+
}
|
|
44
|
+
this.updateInterval = setInterval(() => {
|
|
45
|
+
this.calculateAndNotify();
|
|
46
|
+
}, this.options.updateIntervalMs);
|
|
47
|
+
// Initial calculation
|
|
48
|
+
this.calculateAndNotify();
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Stop continuous trust monitoring
|
|
52
|
+
*/
|
|
53
|
+
stop() {
|
|
54
|
+
if (this.updateInterval) {
|
|
55
|
+
clearInterval(this.updateInterval);
|
|
56
|
+
this.updateInterval = null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Register a trust signal
|
|
61
|
+
*/
|
|
62
|
+
registerSignal(signal) {
|
|
63
|
+
this.signals.set(signal.id, signal);
|
|
64
|
+
this.evaluateThresholds();
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Update an existing trust signal
|
|
68
|
+
*/
|
|
69
|
+
updateSignal(id, updates) {
|
|
70
|
+
const existing = this.signals.get(id);
|
|
71
|
+
if (existing) {
|
|
72
|
+
this.signals.set(id, { ...existing, ...updates, timestamp: new Date() });
|
|
73
|
+
this.evaluateThresholds();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Remove a trust signal
|
|
78
|
+
*/
|
|
79
|
+
removeSignal(id) {
|
|
80
|
+
this.signals.delete(id);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get current trust score
|
|
84
|
+
*/
|
|
85
|
+
getScore() {
|
|
86
|
+
return this.calculateScore();
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get trust history
|
|
90
|
+
*/
|
|
91
|
+
getHistory(hours = 24) {
|
|
92
|
+
const cutoff = new Date(Date.now() - hours * 60 * 60 * 1000);
|
|
93
|
+
return this.history.filter(entry => entry.timestamp >= cutoff);
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get active alerts
|
|
97
|
+
*/
|
|
98
|
+
getAlerts(acknowledged = false) {
|
|
99
|
+
return this.alerts.filter(alert => alert.acknowledged === acknowledged);
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Acknowledge an alert
|
|
103
|
+
*/
|
|
104
|
+
acknowledgeAlert(alertId) {
|
|
105
|
+
const alert = this.alerts.find(a => a.id === alertId);
|
|
106
|
+
if (alert) {
|
|
107
|
+
alert.acknowledged = true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Subscribe to trust score updates
|
|
112
|
+
*/
|
|
113
|
+
subscribe(listener) {
|
|
114
|
+
this.listeners.push(listener);
|
|
115
|
+
return () => {
|
|
116
|
+
this.listeners = this.listeners.filter(l => l !== listener);
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Set custom thresholds
|
|
121
|
+
*/
|
|
122
|
+
setThresholds(thresholds) {
|
|
123
|
+
this.thresholds = thresholds;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Calculate trust score from all signals
|
|
127
|
+
*/
|
|
128
|
+
calculateScore() {
|
|
129
|
+
const signalArray = Array.from(this.signals.values());
|
|
130
|
+
// Group signals by type
|
|
131
|
+
const byType = {
|
|
132
|
+
evidence: signalArray.filter(s => s.type === 'evidence'),
|
|
133
|
+
control: signalArray.filter(s => s.type === 'control'),
|
|
134
|
+
agent: signalArray.filter(s => s.type === 'agent'),
|
|
135
|
+
risk: signalArray.filter(s => s.type === 'risk'),
|
|
136
|
+
behavior: signalArray.filter(s => s.type === 'behavior'),
|
|
137
|
+
external: signalArray.filter(s => s.type === 'external')
|
|
138
|
+
};
|
|
139
|
+
// Calculate weighted average for each type
|
|
140
|
+
const calculateTypeScore = (signals) => {
|
|
141
|
+
if (signals.length === 0)
|
|
142
|
+
return 100; // Default to 100 if no signals
|
|
143
|
+
const totalWeight = signals.reduce((sum, s) => sum + s.weight, 0);
|
|
144
|
+
if (totalWeight === 0)
|
|
145
|
+
return 100;
|
|
146
|
+
return signals.reduce((sum, s) => sum + (s.value * s.weight), 0) / totalWeight;
|
|
147
|
+
};
|
|
148
|
+
const breakdown = {
|
|
149
|
+
evidence: calculateTypeScore(byType.evidence),
|
|
150
|
+
control: calculateTypeScore(byType.control),
|
|
151
|
+
agent: calculateTypeScore(byType.agent),
|
|
152
|
+
risk: calculateTypeScore(byType.risk),
|
|
153
|
+
behavior: calculateTypeScore(byType.behavior),
|
|
154
|
+
external: calculateTypeScore(byType.external)
|
|
155
|
+
};
|
|
156
|
+
// Overall score with weights
|
|
157
|
+
const weights = { evidence: 0.25, control: 0.25, agent: 0.15, risk: 0.15, behavior: 0.1, external: 0.1 };
|
|
158
|
+
const overall = (breakdown.evidence * weights.evidence +
|
|
159
|
+
breakdown.control * weights.control +
|
|
160
|
+
breakdown.agent * weights.agent +
|
|
161
|
+
breakdown.risk * weights.risk +
|
|
162
|
+
breakdown.behavior * weights.behavior +
|
|
163
|
+
breakdown.external * weights.external);
|
|
164
|
+
// Calculate trend
|
|
165
|
+
const previousScore = this.history.length > 0
|
|
166
|
+
? this.history[this.history.length - 1].score.overall
|
|
167
|
+
: overall;
|
|
168
|
+
const trendDelta = overall - previousScore;
|
|
169
|
+
const trend = trendDelta > 2 ? 'improving' : trendDelta < -2 ? 'declining' : 'stable';
|
|
170
|
+
// Filter active alerts
|
|
171
|
+
const activeAlerts = this.alerts.filter(a => !a.acknowledged);
|
|
172
|
+
return {
|
|
173
|
+
overall: Math.round(overall * 100) / 100,
|
|
174
|
+
breakdown: {
|
|
175
|
+
evidence: Math.round(breakdown.evidence * 100) / 100,
|
|
176
|
+
control: Math.round(breakdown.control * 100) / 100,
|
|
177
|
+
agent: Math.round(breakdown.agent * 100) / 100,
|
|
178
|
+
risk: Math.round(breakdown.risk * 100) / 100,
|
|
179
|
+
behavior: Math.round(breakdown.behavior * 100) / 100,
|
|
180
|
+
external: Math.round(breakdown.external * 100) / 100
|
|
181
|
+
},
|
|
182
|
+
trend,
|
|
183
|
+
trendDelta: Math.round(trendDelta * 100) / 100,
|
|
184
|
+
lastUpdated: new Date(),
|
|
185
|
+
nextUpdate: new Date(Date.now() + this.options.updateIntervalMs),
|
|
186
|
+
alerts: activeAlerts
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Calculate score and notify listeners
|
|
191
|
+
*/
|
|
192
|
+
calculateAndNotify() {
|
|
193
|
+
const score = this.calculateScore();
|
|
194
|
+
// Store in history
|
|
195
|
+
this.history.push({
|
|
196
|
+
timestamp: new Date(),
|
|
197
|
+
score,
|
|
198
|
+
signals: Array.from(this.signals.values())
|
|
199
|
+
});
|
|
200
|
+
// Trim history
|
|
201
|
+
const cutoff = new Date(Date.now() - this.options.historyRetentionDays * 24 * 60 * 60 * 1000);
|
|
202
|
+
this.history = this.history.filter(entry => entry.timestamp >= cutoff);
|
|
203
|
+
// Notify listeners
|
|
204
|
+
this.listeners.forEach(listener => listener(score));
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Evaluate thresholds and create alerts
|
|
208
|
+
*/
|
|
209
|
+
evaluateThresholds() {
|
|
210
|
+
const score = this.calculateScore();
|
|
211
|
+
for (const threshold of this.thresholds) {
|
|
212
|
+
const value = this.getMetricValue(score, threshold.metric);
|
|
213
|
+
if (value === null)
|
|
214
|
+
continue;
|
|
215
|
+
let severity = null;
|
|
216
|
+
if (value <= threshold.critical) {
|
|
217
|
+
severity = 'critical';
|
|
218
|
+
}
|
|
219
|
+
else if (value <= threshold.high) {
|
|
220
|
+
severity = 'high';
|
|
221
|
+
}
|
|
222
|
+
else if (value <= threshold.medium) {
|
|
223
|
+
severity = 'medium';
|
|
224
|
+
}
|
|
225
|
+
else if (value <= threshold.low) {
|
|
226
|
+
severity = 'low';
|
|
227
|
+
}
|
|
228
|
+
if (severity) {
|
|
229
|
+
this.createAlert({
|
|
230
|
+
id: `threshold-${threshold.metric}-${Date.now()}`,
|
|
231
|
+
severity,
|
|
232
|
+
type: 'threshold',
|
|
233
|
+
message: `${threshold.metric} score (${value}) below ${severity} threshold`,
|
|
234
|
+
threshold: threshold[severity],
|
|
235
|
+
currentValue: value,
|
|
236
|
+
timestamp: new Date(),
|
|
237
|
+
acknowledged: false
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* Get metric value from score
|
|
244
|
+
*/
|
|
245
|
+
getMetricValue(score, metric) {
|
|
246
|
+
switch (metric) {
|
|
247
|
+
case 'overall': return score.overall;
|
|
248
|
+
case 'evidence': return score.breakdown.evidence;
|
|
249
|
+
case 'control': return score.breakdown.control;
|
|
250
|
+
case 'agent': return score.breakdown.agent;
|
|
251
|
+
case 'risk': return score.breakdown.risk;
|
|
252
|
+
case 'behavior': return score.breakdown.behavior;
|
|
253
|
+
case 'external': return score.breakdown.external;
|
|
254
|
+
default: return null;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Create a new alert
|
|
259
|
+
*/
|
|
260
|
+
createAlert(alert) {
|
|
261
|
+
this.alerts.push(alert);
|
|
262
|
+
// Trim alerts
|
|
263
|
+
if (this.alerts.length > this.options.maxAlerts) {
|
|
264
|
+
this.alerts = this.alerts.slice(-this.options.maxAlerts);
|
|
265
|
+
}
|
|
266
|
+
// Auto-acknowledge old alerts
|
|
267
|
+
if (this.options.autoAcknowledgeAfterMs) {
|
|
268
|
+
const cutoff = new Date(Date.now() - this.options.autoAcknowledgeAfterMs);
|
|
269
|
+
this.alerts.forEach(a => {
|
|
270
|
+
if (a.timestamp < cutoff && !a.acknowledged) {
|
|
271
|
+
a.acknowledged = true;
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Initialize default thresholds
|
|
278
|
+
*/
|
|
279
|
+
initializeDefaultThresholds() {
|
|
280
|
+
this.thresholds = [
|
|
281
|
+
{ metric: 'overall', critical: 30, high: 50, medium: 70, low: 85 },
|
|
282
|
+
{ metric: 'evidence', critical: 20, high: 40, medium: 60, low: 80 },
|
|
283
|
+
{ metric: 'control', critical: 25, high: 45, medium: 65, low: 85 },
|
|
284
|
+
{ metric: 'agent', critical: 30, high: 50, medium: 70, low: 85 },
|
|
285
|
+
{ metric: 'risk', critical: 20, high: 40, medium: 60, low: 80 }
|
|
286
|
+
];
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
exports.ContinuousTrustEngine = ContinuousTrustEngine;
|
|
290
|
+
// trigger publish
|
|
291
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@grc-claw/continuous-trust-engine",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "Real-time trust scoring for compliance posture",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"access": "public"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc",
|
|
13
|
+
"test": "node --test dist/**/*.test.js"
|
|
14
|
+
},
|
|
15
|
+
"dependencies": {},
|
|
16
|
+
"devDependencies": {
|
|
17
|
+
"typescript": "^5.7.0"
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ContinuousTrustEngine - Real-time trust scoring for compliance posture
|
|
3
|
+
*
|
|
4
|
+
* Continuously evaluates compliance posture, evidence quality, agent behavior,
|
|
5
|
+
* and organizational trust signals to produce a dynamic trust score.
|
|
6
|
+
*
|
|
7
|
+
* This engine goes beyond static compliance checks by incorporating:
|
|
8
|
+
* - Real-time evidence freshness scoring
|
|
9
|
+
* - Agent behavioral trust signals
|
|
10
|
+
* - Control effectiveness metrics
|
|
11
|
+
* - Risk-adjusted trust calculations
|
|
12
|
+
* - Trust decay over time
|
|
13
|
+
* - Trust threshold alerts
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
export interface TrustSignal {
|
|
17
|
+
id: string;
|
|
18
|
+
type: 'evidence' | 'control' | 'agent' | 'risk' | 'behavior' | 'external';
|
|
19
|
+
name: string;
|
|
20
|
+
value: number; // 0-100
|
|
21
|
+
weight: number; // 0-1
|
|
22
|
+
timestamp: Date;
|
|
23
|
+
metadata: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface TrustScore {
|
|
27
|
+
overall: number; // 0-100
|
|
28
|
+
breakdown: {
|
|
29
|
+
evidence: number;
|
|
30
|
+
control: number;
|
|
31
|
+
agent: number;
|
|
32
|
+
risk: number;
|
|
33
|
+
behavior: number;
|
|
34
|
+
external: number;
|
|
35
|
+
};
|
|
36
|
+
trend: 'improving' | 'stable' | 'declining';
|
|
37
|
+
trendDelta: number; // change from previous period
|
|
38
|
+
lastUpdated: Date;
|
|
39
|
+
nextUpdate: Date;
|
|
40
|
+
alerts: TrustAlert[];
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export interface TrustAlert {
|
|
44
|
+
id: string;
|
|
45
|
+
severity: 'critical' | 'high' | 'medium' | 'low';
|
|
46
|
+
type: string;
|
|
47
|
+
message: string;
|
|
48
|
+
threshold: number;
|
|
49
|
+
currentValue: number;
|
|
50
|
+
timestamp: Date;
|
|
51
|
+
acknowledged: boolean;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export interface TrustThreshold {
|
|
55
|
+
metric: string;
|
|
56
|
+
critical: number;
|
|
57
|
+
high: number;
|
|
58
|
+
medium: number;
|
|
59
|
+
low: number;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export interface TrustHistoryEntry {
|
|
63
|
+
timestamp: Date;
|
|
64
|
+
score: TrustScore;
|
|
65
|
+
signals: TrustSignal[];
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export class ContinuousTrustEngine {
|
|
69
|
+
private signals: Map<string, TrustSignal> = new Map();
|
|
70
|
+
private history: TrustHistoryEntry[] = [];
|
|
71
|
+
private thresholds: TrustThreshold[] = [];
|
|
72
|
+
private alerts: TrustAlert[] = [];
|
|
73
|
+
private updateInterval: NodeJS.Timeout | null = null;
|
|
74
|
+
private listeners: ((score: TrustScore) => void)[] = [];
|
|
75
|
+
|
|
76
|
+
constructor(
|
|
77
|
+
private readonly options: {
|
|
78
|
+
updateIntervalMs?: number;
|
|
79
|
+
historyRetentionDays?: number;
|
|
80
|
+
maxAlerts?: number;
|
|
81
|
+
autoAcknowledgeAfterMs?: number;
|
|
82
|
+
} = {}
|
|
83
|
+
) {
|
|
84
|
+
this.options = {
|
|
85
|
+
updateIntervalMs: 60000, // 1 minute
|
|
86
|
+
historyRetentionDays: 90,
|
|
87
|
+
maxAlerts: 1000,
|
|
88
|
+
autoAcknowledgeAfterMs: 86400000, // 24 hours
|
|
89
|
+
...options
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
this.initializeDefaultThresholds();
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Start continuous trust monitoring
|
|
97
|
+
*/
|
|
98
|
+
start(): void {
|
|
99
|
+
if (this.updateInterval) {
|
|
100
|
+
return; // Already running
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
this.updateInterval = setInterval(() => {
|
|
104
|
+
this.calculateAndNotify();
|
|
105
|
+
}, this.options.updateIntervalMs);
|
|
106
|
+
|
|
107
|
+
// Initial calculation
|
|
108
|
+
this.calculateAndNotify();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Stop continuous trust monitoring
|
|
113
|
+
*/
|
|
114
|
+
stop(): void {
|
|
115
|
+
if (this.updateInterval) {
|
|
116
|
+
clearInterval(this.updateInterval);
|
|
117
|
+
this.updateInterval = null;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Register a trust signal
|
|
123
|
+
*/
|
|
124
|
+
registerSignal(signal: TrustSignal): void {
|
|
125
|
+
this.signals.set(signal.id, signal);
|
|
126
|
+
this.evaluateThresholds();
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Update an existing trust signal
|
|
131
|
+
*/
|
|
132
|
+
updateSignal(id: string, updates: Partial<TrustSignal>): void {
|
|
133
|
+
const existing = this.signals.get(id);
|
|
134
|
+
if (existing) {
|
|
135
|
+
this.signals.set(id, { ...existing, ...updates, timestamp: new Date() });
|
|
136
|
+
this.evaluateThresholds();
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Remove a trust signal
|
|
142
|
+
*/
|
|
143
|
+
removeSignal(id: string): void {
|
|
144
|
+
this.signals.delete(id);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Get current trust score
|
|
149
|
+
*/
|
|
150
|
+
getScore(): TrustScore {
|
|
151
|
+
return this.calculateScore();
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get trust history
|
|
156
|
+
*/
|
|
157
|
+
getHistory(hours: number = 24): TrustHistoryEntry[] {
|
|
158
|
+
const cutoff = new Date(Date.now() - hours * 60 * 60 * 1000);
|
|
159
|
+
return this.history.filter(entry => entry.timestamp >= cutoff);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Get active alerts
|
|
164
|
+
*/
|
|
165
|
+
getAlerts(acknowledged: boolean = false): TrustAlert[] {
|
|
166
|
+
return this.alerts.filter(alert => alert.acknowledged === acknowledged);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Acknowledge an alert
|
|
171
|
+
*/
|
|
172
|
+
acknowledgeAlert(alertId: string): void {
|
|
173
|
+
const alert = this.alerts.find(a => a.id === alertId);
|
|
174
|
+
if (alert) {
|
|
175
|
+
alert.acknowledged = true;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Subscribe to trust score updates
|
|
181
|
+
*/
|
|
182
|
+
subscribe(listener: (score: TrustScore) => void): () => void {
|
|
183
|
+
this.listeners.push(listener);
|
|
184
|
+
return () => {
|
|
185
|
+
this.listeners = this.listeners.filter(l => l !== listener);
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Set custom thresholds
|
|
191
|
+
*/
|
|
192
|
+
setThresholds(thresholds: TrustThreshold[]): void {
|
|
193
|
+
this.thresholds = thresholds;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Calculate trust score from all signals
|
|
198
|
+
*/
|
|
199
|
+
private calculateScore(): TrustScore {
|
|
200
|
+
const signalArray = Array.from(this.signals.values());
|
|
201
|
+
|
|
202
|
+
// Group signals by type
|
|
203
|
+
const byType = {
|
|
204
|
+
evidence: signalArray.filter(s => s.type === 'evidence'),
|
|
205
|
+
control: signalArray.filter(s => s.type === 'control'),
|
|
206
|
+
agent: signalArray.filter(s => s.type === 'agent'),
|
|
207
|
+
risk: signalArray.filter(s => s.type === 'risk'),
|
|
208
|
+
behavior: signalArray.filter(s => s.type === 'behavior'),
|
|
209
|
+
external: signalArray.filter(s => s.type === 'external')
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
// Calculate weighted average for each type
|
|
213
|
+
const calculateTypeScore = (signals: TrustSignal[]): number => {
|
|
214
|
+
if (signals.length === 0) return 100; // Default to 100 if no signals
|
|
215
|
+
const totalWeight = signals.reduce((sum, s) => sum + s.weight, 0);
|
|
216
|
+
if (totalWeight === 0) return 100;
|
|
217
|
+
return signals.reduce((sum, s) => sum + (s.value * s.weight), 0) / totalWeight;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
const breakdown = {
|
|
221
|
+
evidence: calculateTypeScore(byType.evidence),
|
|
222
|
+
control: calculateTypeScore(byType.control),
|
|
223
|
+
agent: calculateTypeScore(byType.agent),
|
|
224
|
+
risk: calculateTypeScore(byType.risk),
|
|
225
|
+
behavior: calculateTypeScore(byType.behavior),
|
|
226
|
+
external: calculateTypeScore(byType.external)
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
// Overall score with weights
|
|
230
|
+
const weights = { evidence: 0.25, control: 0.25, agent: 0.15, risk: 0.15, behavior: 0.1, external: 0.1 };
|
|
231
|
+
const overall = (
|
|
232
|
+
breakdown.evidence * weights.evidence +
|
|
233
|
+
breakdown.control * weights.control +
|
|
234
|
+
breakdown.agent * weights.agent +
|
|
235
|
+
breakdown.risk * weights.risk +
|
|
236
|
+
breakdown.behavior * weights.behavior +
|
|
237
|
+
breakdown.external * weights.external
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
// Calculate trend
|
|
241
|
+
const previousScore = this.history.length > 0
|
|
242
|
+
? this.history[this.history.length - 1].score.overall
|
|
243
|
+
: overall;
|
|
244
|
+
const trendDelta = overall - previousScore;
|
|
245
|
+
const trend = trendDelta > 2 ? 'improving' : trendDelta < -2 ? 'declining' : 'stable';
|
|
246
|
+
|
|
247
|
+
// Filter active alerts
|
|
248
|
+
const activeAlerts = this.alerts.filter(a => !a.acknowledged);
|
|
249
|
+
|
|
250
|
+
return {
|
|
251
|
+
overall: Math.round(overall * 100) / 100,
|
|
252
|
+
breakdown: {
|
|
253
|
+
evidence: Math.round(breakdown.evidence * 100) / 100,
|
|
254
|
+
control: Math.round(breakdown.control * 100) / 100,
|
|
255
|
+
agent: Math.round(breakdown.agent * 100) / 100,
|
|
256
|
+
risk: Math.round(breakdown.risk * 100) / 100,
|
|
257
|
+
behavior: Math.round(breakdown.behavior * 100) / 100,
|
|
258
|
+
external: Math.round(breakdown.external * 100) / 100
|
|
259
|
+
},
|
|
260
|
+
trend,
|
|
261
|
+
trendDelta: Math.round(trendDelta * 100) / 100,
|
|
262
|
+
lastUpdated: new Date(),
|
|
263
|
+
nextUpdate: new Date(Date.now() + this.options.updateIntervalMs!),
|
|
264
|
+
alerts: activeAlerts
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
/**
|
|
269
|
+
* Calculate score and notify listeners
|
|
270
|
+
*/
|
|
271
|
+
private calculateAndNotify(): void {
|
|
272
|
+
const score = this.calculateScore();
|
|
273
|
+
|
|
274
|
+
// Store in history
|
|
275
|
+
this.history.push({
|
|
276
|
+
timestamp: new Date(),
|
|
277
|
+
score,
|
|
278
|
+
signals: Array.from(this.signals.values())
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
// Trim history
|
|
282
|
+
const cutoff = new Date(Date.now() - this.options.historyRetentionDays! * 24 * 60 * 60 * 1000);
|
|
283
|
+
this.history = this.history.filter(entry => entry.timestamp >= cutoff);
|
|
284
|
+
|
|
285
|
+
// Notify listeners
|
|
286
|
+
this.listeners.forEach(listener => listener(score));
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Evaluate thresholds and create alerts
|
|
291
|
+
*/
|
|
292
|
+
private evaluateThresholds(): void {
|
|
293
|
+
const score = this.calculateScore();
|
|
294
|
+
|
|
295
|
+
for (const threshold of this.thresholds) {
|
|
296
|
+
const value = this.getMetricValue(score, threshold.metric);
|
|
297
|
+
if (value === null) continue;
|
|
298
|
+
|
|
299
|
+
let severity: TrustAlert['severity'] | null = null;
|
|
300
|
+
|
|
301
|
+
if (value <= threshold.critical) {
|
|
302
|
+
severity = 'critical';
|
|
303
|
+
} else if (value <= threshold.high) {
|
|
304
|
+
severity = 'high';
|
|
305
|
+
} else if (value <= threshold.medium) {
|
|
306
|
+
severity = 'medium';
|
|
307
|
+
} else if (value <= threshold.low) {
|
|
308
|
+
severity = 'low';
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
if (severity) {
|
|
312
|
+
this.createAlert({
|
|
313
|
+
id: `threshold-${threshold.metric}-${Date.now()}`,
|
|
314
|
+
severity,
|
|
315
|
+
type: 'threshold',
|
|
316
|
+
message: `${threshold.metric} score (${value}) below ${severity} threshold`,
|
|
317
|
+
threshold: threshold[severity],
|
|
318
|
+
currentValue: value,
|
|
319
|
+
timestamp: new Date(),
|
|
320
|
+
acknowledged: false
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Get metric value from score
|
|
328
|
+
*/
|
|
329
|
+
private getMetricValue(score: TrustScore, metric: string): number | null {
|
|
330
|
+
switch (metric) {
|
|
331
|
+
case 'overall': return score.overall;
|
|
332
|
+
case 'evidence': return score.breakdown.evidence;
|
|
333
|
+
case 'control': return score.breakdown.control;
|
|
334
|
+
case 'agent': return score.breakdown.agent;
|
|
335
|
+
case 'risk': return score.breakdown.risk;
|
|
336
|
+
case 'behavior': return score.breakdown.behavior;
|
|
337
|
+
case 'external': return score.breakdown.external;
|
|
338
|
+
default: return null;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Create a new alert
|
|
344
|
+
*/
|
|
345
|
+
private createAlert(alert: TrustAlert): void {
|
|
346
|
+
this.alerts.push(alert);
|
|
347
|
+
|
|
348
|
+
// Trim alerts
|
|
349
|
+
if (this.alerts.length > this.options.maxAlerts!) {
|
|
350
|
+
this.alerts = this.alerts.slice(-this.options.maxAlerts!);
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Auto-acknowledge old alerts
|
|
354
|
+
if (this.options.autoAcknowledgeAfterMs) {
|
|
355
|
+
const cutoff = new Date(Date.now() - this.options.autoAcknowledgeAfterMs);
|
|
356
|
+
this.alerts.forEach(a => {
|
|
357
|
+
if (a.timestamp < cutoff && !a.acknowledged) {
|
|
358
|
+
a.acknowledged = true;
|
|
359
|
+
}
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/**
|
|
365
|
+
* Initialize default thresholds
|
|
366
|
+
*/
|
|
367
|
+
private initializeDefaultThresholds(): void {
|
|
368
|
+
this.thresholds = [
|
|
369
|
+
{ metric: 'overall', critical: 30, high: 50, medium: 70, low: 85 },
|
|
370
|
+
{ metric: 'evidence', critical: 20, high: 40, medium: 60, low: 80 },
|
|
371
|
+
{ metric: 'control', critical: 25, high: 45, medium: 65, low: 85 },
|
|
372
|
+
{ metric: 'agent', critical: 30, high: 50, medium: 70, low: 85 },
|
|
373
|
+
{ metric: 'risk', critical: 20, high: 40, medium: 60, low: 80 }
|
|
374
|
+
];
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
// trigger publish
|