tlc-claude-code 1.3.0 → 1.4.1
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/dashboard/dist/components/AuditPane.d.ts +30 -0
- package/dashboard/dist/components/AuditPane.js +127 -0
- package/dashboard/dist/components/AuditPane.test.d.ts +1 -0
- package/dashboard/dist/components/AuditPane.test.js +339 -0
- package/dashboard/dist/components/CompliancePane.d.ts +39 -0
- package/dashboard/dist/components/CompliancePane.js +96 -0
- package/dashboard/dist/components/CompliancePane.test.d.ts +1 -0
- package/dashboard/dist/components/CompliancePane.test.js +183 -0
- package/dashboard/dist/components/SSOPane.d.ts +36 -0
- package/dashboard/dist/components/SSOPane.js +71 -0
- package/dashboard/dist/components/SSOPane.test.d.ts +1 -0
- package/dashboard/dist/components/SSOPane.test.js +155 -0
- package/dashboard/dist/components/WorkspaceDocsPane.js +0 -16
- package/dashboard/dist/components/WorkspacePane.d.ts +1 -1
- package/dashboard/dist/components/ZeroRetentionPane.d.ts +44 -0
- package/dashboard/dist/components/ZeroRetentionPane.js +83 -0
- package/dashboard/dist/components/ZeroRetentionPane.test.d.ts +1 -0
- package/dashboard/dist/components/ZeroRetentionPane.test.js +160 -0
- package/package.json +1 -1
- package/server/lib/access-control-doc.js +541 -0
- package/server/lib/access-control-doc.test.js +672 -0
- package/server/lib/adr-generator.js +423 -0
- package/server/lib/adr-generator.test.js +586 -0
- package/server/lib/agent-progress-monitor.js +223 -0
- package/server/lib/agent-progress-monitor.test.js +202 -0
- package/server/lib/audit-attribution.js +191 -0
- package/server/lib/audit-attribution.test.js +359 -0
- package/server/lib/audit-classifier.js +202 -0
- package/server/lib/audit-classifier.test.js +209 -0
- package/server/lib/audit-command.js +275 -0
- package/server/lib/audit-command.test.js +325 -0
- package/server/lib/audit-exporter.js +380 -0
- package/server/lib/audit-exporter.test.js +464 -0
- package/server/lib/audit-logger.js +236 -0
- package/server/lib/audit-logger.test.js +364 -0
- package/server/lib/audit-query.js +257 -0
- package/server/lib/audit-query.test.js +352 -0
- package/server/lib/audit-storage.js +269 -0
- package/server/lib/audit-storage.test.js +272 -0
- package/server/lib/bulk-repo-init.js +342 -0
- package/server/lib/bulk-repo-init.test.js +388 -0
- package/server/lib/compliance-checklist.js +866 -0
- package/server/lib/compliance-checklist.test.js +476 -0
- package/server/lib/compliance-command.js +616 -0
- package/server/lib/compliance-command.test.js +551 -0
- package/server/lib/compliance-reporter.js +692 -0
- package/server/lib/compliance-reporter.test.js +707 -0
- package/server/lib/data-flow-doc.js +665 -0
- package/server/lib/data-flow-doc.test.js +659 -0
- package/server/lib/ephemeral-storage.js +249 -0
- package/server/lib/ephemeral-storage.test.js +254 -0
- package/server/lib/evidence-collector.js +627 -0
- package/server/lib/evidence-collector.test.js +901 -0
- package/server/lib/flow-diagram-generator.js +474 -0
- package/server/lib/flow-diagram-generator.test.js +446 -0
- package/server/lib/idp-manager.js +626 -0
- package/server/lib/idp-manager.test.js +587 -0
- package/server/lib/memory-exclusion.js +326 -0
- package/server/lib/memory-exclusion.test.js +241 -0
- package/server/lib/mfa-handler.js +452 -0
- package/server/lib/mfa-handler.test.js +490 -0
- package/server/lib/oauth-flow.js +375 -0
- package/server/lib/oauth-flow.test.js +487 -0
- package/server/lib/oauth-registry.js +190 -0
- package/server/lib/oauth-registry.test.js +306 -0
- package/server/lib/readme-generator.js +490 -0
- package/server/lib/readme-generator.test.js +493 -0
- package/server/lib/repo-dependency-tracker.js +261 -0
- package/server/lib/repo-dependency-tracker.test.js +350 -0
- package/server/lib/retention-policy.js +281 -0
- package/server/lib/retention-policy.test.js +486 -0
- package/server/lib/role-mapper.js +236 -0
- package/server/lib/role-mapper.test.js +395 -0
- package/server/lib/saml-provider.js +765 -0
- package/server/lib/saml-provider.test.js +643 -0
- package/server/lib/security-policy-generator.js +682 -0
- package/server/lib/security-policy-generator.test.js +544 -0
- package/server/lib/sensitive-detector.js +112 -0
- package/server/lib/sensitive-detector.test.js +209 -0
- package/server/lib/service-interaction-diagram.js +700 -0
- package/server/lib/service-interaction-diagram.test.js +638 -0
- package/server/lib/service-summary.js +553 -0
- package/server/lib/service-summary.test.js +619 -0
- package/server/lib/session-purge.js +460 -0
- package/server/lib/session-purge.test.js +312 -0
- package/server/lib/sso-command.js +544 -0
- package/server/lib/sso-command.test.js +552 -0
- package/server/lib/sso-session.js +492 -0
- package/server/lib/sso-session.test.js +670 -0
- package/server/lib/workspace-command.js +249 -0
- package/server/lib/workspace-command.test.js +264 -0
- package/server/lib/workspace-config.js +270 -0
- package/server/lib/workspace-config.test.js +312 -0
- package/server/lib/workspace-docs-command.js +547 -0
- package/server/lib/workspace-docs-command.test.js +692 -0
- package/server/lib/workspace-memory.js +451 -0
- package/server/lib/workspace-memory.test.js +403 -0
- package/server/lib/workspace-scanner.js +452 -0
- package/server/lib/workspace-scanner.test.js +677 -0
- package/server/lib/workspace-test-runner.js +315 -0
- package/server/lib/workspace-test-runner.test.js +294 -0
- package/server/lib/zero-retention-command.js +439 -0
- package/server/lib/zero-retention-command.test.js +448 -0
- package/server/lib/zero-retention.js +322 -0
- package/server/lib/zero-retention.test.js +258 -0
|
@@ -0,0 +1,460 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session Purge Manager - Automatically purge data when sessions end
|
|
3
|
+
*
|
|
4
|
+
* Provides:
|
|
5
|
+
* - Session-end detection and data purging
|
|
6
|
+
* - Policy-based retention evaluation
|
|
7
|
+
* - Process exit and timeout handling
|
|
8
|
+
* - Audit logging for purge operations
|
|
9
|
+
* - Graceful and forced shutdown support
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
const { getPolicy, evaluateRetention } = require('./retention-policy.js');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Session Purge Manager
|
|
16
|
+
*
|
|
17
|
+
* Manages automatic purging of session data based on session lifecycle events
|
|
18
|
+
*/
|
|
19
|
+
class SessionPurgeManager {
|
|
20
|
+
/**
|
|
21
|
+
* Create a session purge manager
|
|
22
|
+
* @param {Object} options - Configuration options
|
|
23
|
+
* @param {Object} options.storage - EphemeralStorage instance to manage
|
|
24
|
+
* @param {string} [options.sessionId] - Current session ID
|
|
25
|
+
* @param {boolean} [options.auditEnabled] - Enable audit logging
|
|
26
|
+
* @param {Function} [options.onAuditLog] - Callback for audit log entries
|
|
27
|
+
* @param {Object} [options.policies] - Custom retention policies
|
|
28
|
+
*/
|
|
29
|
+
constructor(options = {}) {
|
|
30
|
+
this.storage = options.storage;
|
|
31
|
+
this.sessionId = options.sessionId || this._generateSessionId();
|
|
32
|
+
this.auditEnabled = options.auditEnabled || false;
|
|
33
|
+
this.onAuditLog = options.onAuditLog || null;
|
|
34
|
+
this.policies = options.policies || null;
|
|
35
|
+
|
|
36
|
+
// Track purge history
|
|
37
|
+
this.purgeHistory = [];
|
|
38
|
+
this.lastPurge = null;
|
|
39
|
+
|
|
40
|
+
// Idle timer
|
|
41
|
+
this.idleTimer = null;
|
|
42
|
+
this.idleTimeout = null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Generate a unique session ID
|
|
47
|
+
* @private
|
|
48
|
+
*/
|
|
49
|
+
_generateSessionId() {
|
|
50
|
+
return `session-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Log an audit entry if audit is enabled
|
|
55
|
+
* @private
|
|
56
|
+
*/
|
|
57
|
+
_logAudit(entry) {
|
|
58
|
+
if (this.auditEnabled && this.onAuditLog) {
|
|
59
|
+
const auditEntry = {
|
|
60
|
+
timestamp: new Date().toISOString(),
|
|
61
|
+
sessionId: this.sessionId,
|
|
62
|
+
...entry,
|
|
63
|
+
};
|
|
64
|
+
this.onAuditLog(auditEntry);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get all keys from storage with their values
|
|
70
|
+
* @private
|
|
71
|
+
*/
|
|
72
|
+
_getAllEntries() {
|
|
73
|
+
const entries = [];
|
|
74
|
+
const keys = this.storage.keys();
|
|
75
|
+
for (const key of keys) {
|
|
76
|
+
const value = this.storage.get(key);
|
|
77
|
+
entries.push({ key, value });
|
|
78
|
+
}
|
|
79
|
+
return entries;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Handle session end - purge all session-specific data
|
|
84
|
+
* @param {Object} [options] - Purge options
|
|
85
|
+
* @param {boolean} [options.respectPolicies] - Evaluate retention policies before purging
|
|
86
|
+
* @returns {Object} Purge result with count and keys
|
|
87
|
+
*/
|
|
88
|
+
onSessionEnd(options = {}) {
|
|
89
|
+
const purgedKeys = [];
|
|
90
|
+
const entries = this._getAllEntries();
|
|
91
|
+
|
|
92
|
+
for (const { key, value } of entries) {
|
|
93
|
+
let shouldPurge = false;
|
|
94
|
+
|
|
95
|
+
// Check if data belongs to this session
|
|
96
|
+
if (value && typeof value === 'object' && value.sessionId === this.sessionId) {
|
|
97
|
+
shouldPurge = true;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// If respecting policies, evaluate retention
|
|
101
|
+
if (options.respectPolicies && value && typeof value === 'object') {
|
|
102
|
+
const policyOptions = {
|
|
103
|
+
sensitivityLevel: value.sensitivityLevel,
|
|
104
|
+
dataType: value.dataType,
|
|
105
|
+
};
|
|
106
|
+
const policy = getPolicy(policyOptions, this.policies);
|
|
107
|
+
const decision = evaluateRetention(value, policy, {
|
|
108
|
+
currentSessionId: this.sessionId,
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (decision === 'purge') {
|
|
112
|
+
shouldPurge = true;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (shouldPurge) {
|
|
117
|
+
this.storage.delete(key);
|
|
118
|
+
purgedKeys.push(key);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Record this purge
|
|
123
|
+
const purgeRecord = {
|
|
124
|
+
timestamp: new Date().toISOString(),
|
|
125
|
+
sessionId: this.sessionId,
|
|
126
|
+
purgedKeys,
|
|
127
|
+
purgedCount: purgedKeys.length,
|
|
128
|
+
trigger: 'sessionEnd',
|
|
129
|
+
};
|
|
130
|
+
this.purgeHistory.push(purgeRecord);
|
|
131
|
+
this.lastPurge = purgeRecord;
|
|
132
|
+
|
|
133
|
+
// Log audit
|
|
134
|
+
this._logAudit({
|
|
135
|
+
action: 'purge',
|
|
136
|
+
trigger: 'sessionEnd',
|
|
137
|
+
purgedCount: purgedKeys.length,
|
|
138
|
+
keys: purgedKeys,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
purgedKeys,
|
|
143
|
+
purgedCount: purgedKeys.length,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Handle process exit - purge session data
|
|
149
|
+
* @returns {Object} Purge result
|
|
150
|
+
*/
|
|
151
|
+
onProcessExit() {
|
|
152
|
+
const purgedKeys = [];
|
|
153
|
+
const entries = this._getAllEntries();
|
|
154
|
+
|
|
155
|
+
for (const { key, value } of entries) {
|
|
156
|
+
// On process exit, purge session-specific data
|
|
157
|
+
if (value && typeof value === 'object' && value.sessionId === this.sessionId) {
|
|
158
|
+
this.storage.delete(key);
|
|
159
|
+
purgedKeys.push(key);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const purgeRecord = {
|
|
164
|
+
timestamp: new Date().toISOString(),
|
|
165
|
+
sessionId: this.sessionId,
|
|
166
|
+
purgedKeys,
|
|
167
|
+
purgedCount: purgedKeys.length,
|
|
168
|
+
trigger: 'processExit',
|
|
169
|
+
};
|
|
170
|
+
this.purgeHistory.push(purgeRecord);
|
|
171
|
+
this.lastPurge = purgeRecord;
|
|
172
|
+
|
|
173
|
+
this._logAudit({
|
|
174
|
+
action: 'purge',
|
|
175
|
+
trigger: 'processExit',
|
|
176
|
+
purgedCount: purgedKeys.length,
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
return {
|
|
180
|
+
purgedKeys,
|
|
181
|
+
purgedCount: purgedKeys.length,
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Start idle timer - purge after inactivity
|
|
187
|
+
* @param {number} timeout - Idle timeout in milliseconds
|
|
188
|
+
*/
|
|
189
|
+
startIdleTimer(timeout) {
|
|
190
|
+
this.idleTimeout = timeout;
|
|
191
|
+
this._scheduleIdleTimer();
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Reset idle timer on activity
|
|
196
|
+
*/
|
|
197
|
+
resetIdleTimer() {
|
|
198
|
+
if (this.idleTimer) {
|
|
199
|
+
clearTimeout(this.idleTimer);
|
|
200
|
+
this._scheduleIdleTimer();
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
205
|
+
* Stop idle timer
|
|
206
|
+
*/
|
|
207
|
+
stopIdleTimer() {
|
|
208
|
+
if (this.idleTimer) {
|
|
209
|
+
clearTimeout(this.idleTimer);
|
|
210
|
+
this.idleTimer = null;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Schedule the idle timer
|
|
216
|
+
* @private
|
|
217
|
+
*/
|
|
218
|
+
_scheduleIdleTimer() {
|
|
219
|
+
if (this.idleTimeout) {
|
|
220
|
+
this.idleTimer = setTimeout(() => {
|
|
221
|
+
this._onTimeout();
|
|
222
|
+
}, this.idleTimeout);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Handle idle timeout
|
|
228
|
+
* @private
|
|
229
|
+
*/
|
|
230
|
+
_onTimeout() {
|
|
231
|
+
const purgedKeys = [];
|
|
232
|
+
const entries = this._getAllEntries();
|
|
233
|
+
|
|
234
|
+
for (const { key, value } of entries) {
|
|
235
|
+
if (value && typeof value === 'object' && value.sessionId === this.sessionId) {
|
|
236
|
+
this.storage.delete(key);
|
|
237
|
+
purgedKeys.push(key);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const purgeRecord = {
|
|
242
|
+
timestamp: new Date().toISOString(),
|
|
243
|
+
sessionId: this.sessionId,
|
|
244
|
+
purgedKeys,
|
|
245
|
+
purgedCount: purgedKeys.length,
|
|
246
|
+
trigger: 'timeout',
|
|
247
|
+
};
|
|
248
|
+
this.purgeHistory.push(purgeRecord);
|
|
249
|
+
this.lastPurge = purgeRecord;
|
|
250
|
+
|
|
251
|
+
this._logAudit({
|
|
252
|
+
action: 'purge',
|
|
253
|
+
trigger: 'timeout',
|
|
254
|
+
purgedCount: purgedKeys.length,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
return {
|
|
258
|
+
purgedKeys,
|
|
259
|
+
purgedCount: purgedKeys.length,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Purge data matching specific policy criteria
|
|
265
|
+
* @param {Object} criteria - Policy criteria to match
|
|
266
|
+
* @param {string} [criteria.sensitivityLevel] - Sensitivity level to purge
|
|
267
|
+
* @param {string} [criteria.dataType] - Data type to purge
|
|
268
|
+
* @returns {Object} Purge result
|
|
269
|
+
*/
|
|
270
|
+
purgeByPolicy(criteria = {}) {
|
|
271
|
+
const purgedKeys = [];
|
|
272
|
+
const entries = this._getAllEntries();
|
|
273
|
+
|
|
274
|
+
for (const { key, value } of entries) {
|
|
275
|
+
if (!value || typeof value !== 'object') continue;
|
|
276
|
+
|
|
277
|
+
let shouldPurge = false;
|
|
278
|
+
|
|
279
|
+
// Match by sensitivity level
|
|
280
|
+
if (criteria.sensitivityLevel && value.sensitivityLevel === criteria.sensitivityLevel) {
|
|
281
|
+
shouldPurge = true;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// Match by data type
|
|
285
|
+
if (criteria.dataType && value.dataType === criteria.dataType) {
|
|
286
|
+
shouldPurge = true;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (shouldPurge) {
|
|
290
|
+
this.storage.delete(key);
|
|
291
|
+
purgedKeys.push(key);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
const purgeRecord = {
|
|
296
|
+
timestamp: new Date().toISOString(),
|
|
297
|
+
sessionId: this.sessionId,
|
|
298
|
+
purgedKeys,
|
|
299
|
+
purgedCount: purgedKeys.length,
|
|
300
|
+
trigger: 'policy',
|
|
301
|
+
criteria,
|
|
302
|
+
};
|
|
303
|
+
this.purgeHistory.push(purgeRecord);
|
|
304
|
+
this.lastPurge = purgeRecord;
|
|
305
|
+
|
|
306
|
+
this._logAudit({
|
|
307
|
+
action: 'purge',
|
|
308
|
+
trigger: 'policy',
|
|
309
|
+
criteria,
|
|
310
|
+
purgedCount: purgedKeys.length,
|
|
311
|
+
});
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
purgedKeys,
|
|
315
|
+
purgedCount: purgedKeys.length,
|
|
316
|
+
};
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Force purge all data immediately
|
|
321
|
+
* @returns {Object} Purge result
|
|
322
|
+
*/
|
|
323
|
+
forcePurge() {
|
|
324
|
+
const keys = this.storage.keys();
|
|
325
|
+
const purgedKeys = [...keys];
|
|
326
|
+
const purgedCount = keys.length;
|
|
327
|
+
|
|
328
|
+
this.storage.clear();
|
|
329
|
+
|
|
330
|
+
const purgeRecord = {
|
|
331
|
+
timestamp: new Date().toISOString(),
|
|
332
|
+
sessionId: this.sessionId,
|
|
333
|
+
purgedKeys,
|
|
334
|
+
purgedCount,
|
|
335
|
+
trigger: 'forced',
|
|
336
|
+
forced: true,
|
|
337
|
+
};
|
|
338
|
+
this.purgeHistory.push(purgeRecord);
|
|
339
|
+
this.lastPurge = purgeRecord;
|
|
340
|
+
|
|
341
|
+
this._logAudit({
|
|
342
|
+
action: 'purge',
|
|
343
|
+
trigger: 'forced',
|
|
344
|
+
purgedCount,
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
purgedKeys,
|
|
349
|
+
purgedCount,
|
|
350
|
+
forced: true,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Get report of what was purged
|
|
356
|
+
* @returns {Object} Purge report
|
|
357
|
+
*/
|
|
358
|
+
getPurgeReport() {
|
|
359
|
+
const totalPurged = this.purgeHistory.reduce((sum, record) => sum + record.purgedCount, 0);
|
|
360
|
+
|
|
361
|
+
if (!this.lastPurge) {
|
|
362
|
+
return {
|
|
363
|
+
purgedKeys: [],
|
|
364
|
+
purgedCount: 0,
|
|
365
|
+
timestamp: null,
|
|
366
|
+
sessionId: this.sessionId,
|
|
367
|
+
totalPurged: 0,
|
|
368
|
+
history: [],
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
return {
|
|
373
|
+
purgedKeys: this.lastPurge.purgedKeys,
|
|
374
|
+
purgedCount: this.lastPurge.purgedCount,
|
|
375
|
+
timestamp: this.lastPurge.timestamp,
|
|
376
|
+
sessionId: this.sessionId,
|
|
377
|
+
totalPurged,
|
|
378
|
+
history: this.purgeHistory,
|
|
379
|
+
};
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Perform graceful shutdown with timeout
|
|
384
|
+
* @param {Object} [options] - Shutdown options
|
|
385
|
+
* @param {number} [options.timeout] - Timeout in milliseconds before force purge
|
|
386
|
+
* @returns {Promise<Object>} Shutdown result
|
|
387
|
+
*/
|
|
388
|
+
async gracefulShutdown(options = {}) {
|
|
389
|
+
const timeout = options.timeout || 5000;
|
|
390
|
+
|
|
391
|
+
return new Promise((resolve) => {
|
|
392
|
+
let timedOut = false;
|
|
393
|
+
|
|
394
|
+
// Set up timeout for force purge
|
|
395
|
+
const timeoutId = setTimeout(() => {
|
|
396
|
+
timedOut = true;
|
|
397
|
+
const result = this.forcePurge();
|
|
398
|
+
resolve({
|
|
399
|
+
...result,
|
|
400
|
+
graceful: false,
|
|
401
|
+
timedOut: true,
|
|
402
|
+
});
|
|
403
|
+
}, timeout);
|
|
404
|
+
|
|
405
|
+
// Try graceful purge
|
|
406
|
+
try {
|
|
407
|
+
// Stop idle timer if running
|
|
408
|
+
this.stopIdleTimer();
|
|
409
|
+
|
|
410
|
+
// Purge session data
|
|
411
|
+
const result = this.onSessionEnd({ respectPolicies: true });
|
|
412
|
+
|
|
413
|
+
if (!timedOut) {
|
|
414
|
+
clearTimeout(timeoutId);
|
|
415
|
+
resolve({
|
|
416
|
+
...result,
|
|
417
|
+
graceful: true,
|
|
418
|
+
timedOut: false,
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
} catch (error) {
|
|
422
|
+
if (!timedOut) {
|
|
423
|
+
clearTimeout(timeoutId);
|
|
424
|
+
// On error, force purge
|
|
425
|
+
const result = this.forcePurge();
|
|
426
|
+
resolve({
|
|
427
|
+
...result,
|
|
428
|
+
graceful: false,
|
|
429
|
+
error: error.message,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
/**
|
|
437
|
+
* Register process exit handlers
|
|
438
|
+
*/
|
|
439
|
+
registerProcessHandlers() {
|
|
440
|
+
const exitHandler = () => this.onProcessExit();
|
|
441
|
+
|
|
442
|
+
process.on('exit', exitHandler);
|
|
443
|
+
process.on('SIGINT', exitHandler);
|
|
444
|
+
process.on('SIGTERM', exitHandler);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Factory function to create a SessionPurgeManager
|
|
450
|
+
* @param {Object} options - Configuration options
|
|
451
|
+
* @returns {SessionPurgeManager} New instance
|
|
452
|
+
*/
|
|
453
|
+
function createPurgeManager(options = {}) {
|
|
454
|
+
return new SessionPurgeManager(options);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
module.exports = {
|
|
458
|
+
SessionPurgeManager,
|
|
459
|
+
createPurgeManager,
|
|
460
|
+
};
|