kratos-memory 1.0.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/AGENTS.md +25 -0
- package/LICENSE +21 -0
- package/bin/kratos-cli +7 -0
- package/dist/cli/capture-handler.d.ts +13 -0
- package/dist/cli/capture-handler.d.ts.map +1 -0
- package/dist/cli/capture-handler.js +112 -0
- package/dist/cli/capture-handler.js.map +1 -0
- package/dist/cli/commands/ask.d.ts +5 -0
- package/dist/cli/commands/ask.d.ts.map +1 -0
- package/dist/cli/commands/ask.js +64 -0
- package/dist/cli/commands/ask.js.map +1 -0
- package/dist/cli/commands/capture.d.ts +5 -0
- package/dist/cli/commands/capture.d.ts.map +1 -0
- package/dist/cli/commands/capture.js +31 -0
- package/dist/cli/commands/capture.js.map +1 -0
- package/dist/cli/commands/forget.d.ts +3 -0
- package/dist/cli/commands/forget.d.ts.map +1 -0
- package/dist/cli/commands/forget.js +12 -0
- package/dist/cli/commands/forget.js.map +1 -0
- package/dist/cli/commands/get.d.ts +3 -0
- package/dist/cli/commands/get.d.ts.map +1 -0
- package/dist/cli/commands/get.js +28 -0
- package/dist/cli/commands/get.js.map +1 -0
- package/dist/cli/commands/hooks.d.ts +2 -0
- package/dist/cli/commands/hooks.d.ts.map +1 -0
- package/dist/cli/commands/hooks.js +136 -0
- package/dist/cli/commands/hooks.js.map +1 -0
- package/dist/cli/commands/migrate.d.ts +5 -0
- package/dist/cli/commands/migrate.d.ts.map +1 -0
- package/dist/cli/commands/migrate.js +56 -0
- package/dist/cli/commands/migrate.js.map +1 -0
- package/dist/cli/commands/recent.d.ts +6 -0
- package/dist/cli/commands/recent.d.ts.map +1 -0
- package/dist/cli/commands/recent.js +21 -0
- package/dist/cli/commands/recent.js.map +1 -0
- package/dist/cli/commands/save.d.ts +8 -0
- package/dist/cli/commands/save.d.ts.map +1 -0
- package/dist/cli/commands/save.js +31 -0
- package/dist/cli/commands/save.js.map +1 -0
- package/dist/cli/commands/scan.d.ts +5 -0
- package/dist/cli/commands/scan.d.ts.map +1 -0
- package/dist/cli/commands/scan.js +28 -0
- package/dist/cli/commands/scan.js.map +1 -0
- package/dist/cli/commands/search.d.ts +8 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +45 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/status.d.ts +3 -0
- package/dist/cli/commands/status.d.ts.map +1 -0
- package/dist/cli/commands/status.js +89 -0
- package/dist/cli/commands/status.js.map +1 -0
- package/dist/cli/commands/switch.d.ts +3 -0
- package/dist/cli/commands/switch.d.ts.map +1 -0
- package/dist/cli/commands/switch.js +18 -0
- package/dist/cli/commands/switch.js.map +1 -0
- package/dist/cli/core.d.ts +15 -0
- package/dist/cli/core.d.ts.map +1 -0
- package/dist/cli/core.js +18 -0
- package/dist/cli/core.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +157 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/output.d.ts +22 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +74 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/compression/factory.d.ts +6 -0
- package/dist/compression/factory.d.ts.map +1 -0
- package/dist/compression/factory.js +8 -0
- package/dist/compression/factory.js.map +1 -0
- package/dist/compression/index.d.ts +10 -0
- package/dist/compression/index.d.ts.map +1 -0
- package/dist/compression/index.js +2 -0
- package/dist/compression/index.js.map +1 -0
- package/dist/compression/rule-compressor.d.ts +9 -0
- package/dist/compression/rule-compressor.d.ts.map +1 -0
- package/dist/compression/rule-compressor.js +43 -0
- package/dist/compression/rule-compressor.js.map +1 -0
- package/dist/memory-server/concept-store-enhanced.d.ts +88 -0
- package/dist/memory-server/concept-store-enhanced.d.ts.map +1 -0
- package/dist/memory-server/concept-store-enhanced.js +392 -0
- package/dist/memory-server/concept-store-enhanced.js.map +1 -0
- package/dist/memory-server/concept-store.d.ts +58 -0
- package/dist/memory-server/concept-store.d.ts.map +1 -0
- package/dist/memory-server/concept-store.js +329 -0
- package/dist/memory-server/concept-store.js.map +1 -0
- package/dist/memory-server/context-broker.d.ts +63 -0
- package/dist/memory-server/context-broker.d.ts.map +1 -0
- package/dist/memory-server/context-broker.js +340 -0
- package/dist/memory-server/context-broker.js.map +1 -0
- package/dist/memory-server/database.d.ts +108 -0
- package/dist/memory-server/database.d.ts.map +1 -0
- package/dist/memory-server/database.js +690 -0
- package/dist/memory-server/database.js.map +1 -0
- package/dist/project-manager.d.ts +77 -0
- package/dist/project-manager.d.ts.map +1 -0
- package/dist/project-manager.js +226 -0
- package/dist/project-manager.js.map +1 -0
- package/dist/security/data-retention.d.ts +104 -0
- package/dist/security/data-retention.d.ts.map +1 -0
- package/dist/security/data-retention.js +444 -0
- package/dist/security/data-retention.js.map +1 -0
- package/dist/security/encryption.d.ts +48 -0
- package/dist/security/encryption.d.ts.map +1 -0
- package/dist/security/encryption.js +131 -0
- package/dist/security/encryption.js.map +1 -0
- package/dist/security/pii-detector.d.ts +61 -0
- package/dist/security/pii-detector.d.ts.map +1 -0
- package/dist/security/pii-detector.js +220 -0
- package/dist/security/pii-detector.js.map +1 -0
- package/dist/types/index.d.ts +151 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +10 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +54 -0
|
@@ -0,0 +1,444 @@
|
|
|
1
|
+
import Database from 'better-sqlite3';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { Logger } from '../utils/logger.js';
|
|
5
|
+
import { EncryptionManager } from './encryption.js';
|
|
6
|
+
const logger = new Logger('DataRetention');
|
|
7
|
+
/**
|
|
8
|
+
* Data retention and deletion management
|
|
9
|
+
*/
|
|
10
|
+
export class DataRetentionManager {
|
|
11
|
+
db;
|
|
12
|
+
archiveDb;
|
|
13
|
+
encryption;
|
|
14
|
+
projectId;
|
|
15
|
+
policies = new Map();
|
|
16
|
+
constructor(projectRoot, projectId) {
|
|
17
|
+
this.projectId = projectId;
|
|
18
|
+
// Main database
|
|
19
|
+
const dbPath = path.join(projectRoot, '.kratos', 'memory.db');
|
|
20
|
+
this.db = new Database(dbPath);
|
|
21
|
+
// Archive database
|
|
22
|
+
const archivePath = path.join(projectRoot, '.kratos', 'archive.db');
|
|
23
|
+
fs.ensureDirSync(path.dirname(archivePath));
|
|
24
|
+
this.archiveDb = new Database(archivePath);
|
|
25
|
+
this.initializeArchiveDb();
|
|
26
|
+
// Encryption for archives
|
|
27
|
+
this.encryption = new EncryptionManager(projectRoot, projectId);
|
|
28
|
+
// Load policies
|
|
29
|
+
this.loadPolicies();
|
|
30
|
+
// Start background cleanup
|
|
31
|
+
this.startCleanupScheduler();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Initialize archive database
|
|
35
|
+
*/
|
|
36
|
+
initializeArchiveDb() {
|
|
37
|
+
this.archiveDb.exec(`
|
|
38
|
+
CREATE TABLE IF NOT EXISTS archives (
|
|
39
|
+
id TEXT PRIMARY KEY,
|
|
40
|
+
project_id TEXT NOT NULL,
|
|
41
|
+
memory_id TEXT NOT NULL,
|
|
42
|
+
encrypted_data TEXT NOT NULL,
|
|
43
|
+
archived_at INTEGER NOT NULL,
|
|
44
|
+
expires_at INTEGER NOT NULL,
|
|
45
|
+
metadata TEXT
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
CREATE INDEX IF NOT EXISTS idx_archives_expires ON archives(expires_at);
|
|
49
|
+
CREATE INDEX IF NOT EXISTS idx_archives_project ON archives(project_id);
|
|
50
|
+
`);
|
|
51
|
+
this.archiveDb.exec(`
|
|
52
|
+
CREATE TABLE IF NOT EXISTS deletion_log (
|
|
53
|
+
id TEXT PRIMARY KEY,
|
|
54
|
+
project_id TEXT NOT NULL,
|
|
55
|
+
target_type TEXT NOT NULL,
|
|
56
|
+
target_id TEXT NOT NULL,
|
|
57
|
+
deleted_by TEXT,
|
|
58
|
+
reason TEXT,
|
|
59
|
+
deleted_at INTEGER NOT NULL,
|
|
60
|
+
data_hash TEXT
|
|
61
|
+
);
|
|
62
|
+
`);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Load retention policies
|
|
66
|
+
*/
|
|
67
|
+
loadPolicies() {
|
|
68
|
+
// Default policies
|
|
69
|
+
const defaultPolicies = [
|
|
70
|
+
{
|
|
71
|
+
id: 'default',
|
|
72
|
+
name: 'Default Policy',
|
|
73
|
+
description: 'Standard retention for all memories',
|
|
74
|
+
retentionDays: 90,
|
|
75
|
+
archiveAfterDays: 60,
|
|
76
|
+
deleteAfterDays: 90,
|
|
77
|
+
createdAt: new Date()
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'temporary',
|
|
81
|
+
name: 'Temporary Data',
|
|
82
|
+
description: 'Short-lived data (debugging, logs)',
|
|
83
|
+
retentionDays: 7,
|
|
84
|
+
deleteAfterDays: 7,
|
|
85
|
+
tags: ['temp', 'debug', 'log'],
|
|
86
|
+
createdAt: new Date()
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
id: 'important',
|
|
90
|
+
name: 'Important Data',
|
|
91
|
+
description: 'Long-term retention for critical data',
|
|
92
|
+
retentionDays: 365,
|
|
93
|
+
archiveAfterDays: 180,
|
|
94
|
+
deleteAfterDays: 365,
|
|
95
|
+
importance: 4,
|
|
96
|
+
createdAt: new Date()
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
id: 'permanent',
|
|
100
|
+
name: 'Permanent',
|
|
101
|
+
description: 'Never delete (architecture, decisions)',
|
|
102
|
+
retentionDays: 36500, // 100 years
|
|
103
|
+
deleteAfterDays: 36500,
|
|
104
|
+
importance: 5,
|
|
105
|
+
tags: ['architecture', 'decision', 'permanent'],
|
|
106
|
+
createdAt: new Date()
|
|
107
|
+
}
|
|
108
|
+
];
|
|
109
|
+
for (const policy of defaultPolicies) {
|
|
110
|
+
this.policies.set(policy.id, policy);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Apply retention policy
|
|
115
|
+
*/
|
|
116
|
+
applyPolicy(memoryId, policyId = 'default') {
|
|
117
|
+
const policy = this.policies.get(policyId);
|
|
118
|
+
if (!policy) {
|
|
119
|
+
throw new Error(`Policy not found: ${policyId}`);
|
|
120
|
+
}
|
|
121
|
+
const ttlSeconds = policy.retentionDays * 24 * 60 * 60;
|
|
122
|
+
const expiresAt = Date.now() + (ttlSeconds * 1000);
|
|
123
|
+
// Update memory TTL
|
|
124
|
+
const stmt = this.db.prepare(`
|
|
125
|
+
UPDATE memories
|
|
126
|
+
SET ttl = ?, expires_at = ?
|
|
127
|
+
WHERE id = ? AND project_id = ?
|
|
128
|
+
`);
|
|
129
|
+
stmt.run(ttlSeconds, expiresAt, memoryId, this.projectId);
|
|
130
|
+
logger.info(`Applied policy ${policyId} to memory ${memoryId}`);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Archive old memories
|
|
134
|
+
*/
|
|
135
|
+
async archiveOldMemories() {
|
|
136
|
+
let archived = 0;
|
|
137
|
+
// Check if memories table exists
|
|
138
|
+
const tablesExist = this.db.prepare(`
|
|
139
|
+
SELECT name FROM sqlite_master
|
|
140
|
+
WHERE type='table' AND name='memories'
|
|
141
|
+
`).get();
|
|
142
|
+
if (!tablesExist) {
|
|
143
|
+
return 0; // Tables not initialized yet
|
|
144
|
+
}
|
|
145
|
+
for (const policy of this.policies.values()) {
|
|
146
|
+
if (!policy.archiveAfterDays)
|
|
147
|
+
continue;
|
|
148
|
+
const cutoffTime = Date.now() - (policy.archiveAfterDays * 24 * 60 * 60 * 1000);
|
|
149
|
+
// Find memories to archive (simplified query to avoid sub-select on non-existent table)
|
|
150
|
+
const stmt = this.db.prepare(`
|
|
151
|
+
SELECT * FROM memories
|
|
152
|
+
WHERE project_id = ?
|
|
153
|
+
AND created_at < ?
|
|
154
|
+
`);
|
|
155
|
+
const memories = stmt.all(this.projectId, cutoffTime);
|
|
156
|
+
for (const memory of memories) {
|
|
157
|
+
await this.archiveMemory(memory, policy);
|
|
158
|
+
archived++;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
logger.info(`Archived ${archived} memories`);
|
|
162
|
+
return archived;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Archive a single memory
|
|
166
|
+
*/
|
|
167
|
+
async archiveMemory(memory, policy) {
|
|
168
|
+
// Encrypt memory data
|
|
169
|
+
const encryptedData = this.encryption.encryptJSON(memory);
|
|
170
|
+
// Calculate expiration
|
|
171
|
+
const expiresAt = Date.now() + (policy.deleteAfterDays * 24 * 60 * 60 * 1000);
|
|
172
|
+
// Insert into archive
|
|
173
|
+
const stmt = this.archiveDb.prepare(`
|
|
174
|
+
INSERT INTO archives (id, project_id, memory_id, encrypted_data, archived_at, expires_at, metadata)
|
|
175
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
176
|
+
`);
|
|
177
|
+
const archiveId = `arch_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
178
|
+
const metadata = JSON.stringify({
|
|
179
|
+
originalCreatedAt: memory.created_at,
|
|
180
|
+
importance: memory.importance,
|
|
181
|
+
tags: memory.tags
|
|
182
|
+
});
|
|
183
|
+
stmt.run(archiveId, this.projectId, memory.id, encryptedData, Date.now(), expiresAt, metadata);
|
|
184
|
+
// Delete from main database
|
|
185
|
+
const deleteStmt = this.db.prepare(`
|
|
186
|
+
DELETE FROM memories WHERE id = ? AND project_id = ?
|
|
187
|
+
`);
|
|
188
|
+
deleteStmt.run(memory.id, this.projectId);
|
|
189
|
+
logger.info(`Archived memory ${memory.id}`);
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Restore from archive
|
|
193
|
+
*/
|
|
194
|
+
async restoreFromArchive(memoryId) {
|
|
195
|
+
const stmt = this.archiveDb.prepare(`
|
|
196
|
+
SELECT * FROM archives
|
|
197
|
+
WHERE memory_id = ? AND project_id = ?
|
|
198
|
+
ORDER BY archived_at DESC
|
|
199
|
+
LIMIT 1
|
|
200
|
+
`);
|
|
201
|
+
const archive = stmt.get(memoryId, this.projectId);
|
|
202
|
+
if (!archive) {
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
// Decrypt data
|
|
206
|
+
const memory = this.encryption.decryptJSON(archive.encrypted_data);
|
|
207
|
+
// Restore to main database
|
|
208
|
+
const insertStmt = this.db.prepare(`
|
|
209
|
+
INSERT INTO memories (id, project_id, summary, text, tags, paths, importance, created_at, updated_at)
|
|
210
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
211
|
+
`);
|
|
212
|
+
insertStmt.run(memory.id, memory.project_id, memory.summary, memory.text, JSON.stringify(memory.tags || []), JSON.stringify(memory.paths || []), memory.importance, memory.created_at, Date.now());
|
|
213
|
+
// Remove from archive
|
|
214
|
+
const deleteStmt = this.archiveDb.prepare(`
|
|
215
|
+
DELETE FROM archives WHERE id = ?
|
|
216
|
+
`);
|
|
217
|
+
deleteStmt.run(archive.id);
|
|
218
|
+
logger.info(`Restored memory ${memoryId} from archive`);
|
|
219
|
+
return true;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Delete data permanently (GDPR right to erasure)
|
|
223
|
+
*/
|
|
224
|
+
async deleteData(request) {
|
|
225
|
+
const deletionId = `del_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
226
|
+
// Log deletion request
|
|
227
|
+
const logStmt = this.archiveDb.prepare(`
|
|
228
|
+
INSERT INTO deletion_log (id, project_id, target_type, target_id, deleted_by, reason, deleted_at)
|
|
229
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
230
|
+
`);
|
|
231
|
+
logStmt.run(deletionId, this.projectId, request.targetType, request.targetId, request.userId, request.reason, Date.now());
|
|
232
|
+
switch (request.targetType) {
|
|
233
|
+
case 'memory':
|
|
234
|
+
await this.deleteMemory(request.targetId);
|
|
235
|
+
break;
|
|
236
|
+
case 'project':
|
|
237
|
+
await this.deleteProject(request.targetId);
|
|
238
|
+
break;
|
|
239
|
+
case 'user':
|
|
240
|
+
await this.deleteUserData(request.targetId);
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
logger.info(`Completed deletion: ${deletionId}`);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Delete a single memory
|
|
247
|
+
*/
|
|
248
|
+
async deleteMemory(memoryId) {
|
|
249
|
+
// Delete from main database
|
|
250
|
+
const stmt = this.db.prepare(`
|
|
251
|
+
DELETE FROM memories WHERE id = ? AND project_id = ?
|
|
252
|
+
`);
|
|
253
|
+
stmt.run(memoryId, this.projectId);
|
|
254
|
+
// Delete from FTS
|
|
255
|
+
const ftsStmt = this.db.prepare(`
|
|
256
|
+
DELETE FROM memories_fts WHERE rowid = (
|
|
257
|
+
SELECT rowid FROM memories WHERE id = ? AND project_id = ?
|
|
258
|
+
)
|
|
259
|
+
`);
|
|
260
|
+
ftsStmt.run(memoryId, this.projectId);
|
|
261
|
+
// Delete from archives
|
|
262
|
+
const archiveStmt = this.archiveDb.prepare(`
|
|
263
|
+
DELETE FROM archives WHERE memory_id = ? AND project_id = ?
|
|
264
|
+
`);
|
|
265
|
+
archiveStmt.run(memoryId, this.projectId);
|
|
266
|
+
logger.info(`Deleted memory ${memoryId}`);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Delete entire project
|
|
270
|
+
*/
|
|
271
|
+
async deleteProject(projectId) {
|
|
272
|
+
if (projectId !== this.projectId) {
|
|
273
|
+
throw new Error('Can only delete current project');
|
|
274
|
+
}
|
|
275
|
+
// Delete all memories
|
|
276
|
+
const stmt = this.db.prepare(`
|
|
277
|
+
DELETE FROM memories WHERE project_id = ?
|
|
278
|
+
`);
|
|
279
|
+
const result = stmt.run(projectId);
|
|
280
|
+
// Delete all archives
|
|
281
|
+
const archiveStmt = this.archiveDb.prepare(`
|
|
282
|
+
DELETE FROM archives WHERE project_id = ?
|
|
283
|
+
`);
|
|
284
|
+
archiveStmt.run(projectId);
|
|
285
|
+
// Destroy encryption key
|
|
286
|
+
this.encryption.destroyKey();
|
|
287
|
+
logger.info(`Deleted project ${projectId} (${result.changes} memories)`);
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Delete all user data (GDPR)
|
|
291
|
+
*/
|
|
292
|
+
async deleteUserData(userId) {
|
|
293
|
+
// This would integrate with RBAC to find all user data
|
|
294
|
+
// For now, delete memories created by user
|
|
295
|
+
const stmt = this.db.prepare(`
|
|
296
|
+
DELETE FROM memories
|
|
297
|
+
WHERE project_id = ?
|
|
298
|
+
AND json_extract(metadata, '$.userId') = ?
|
|
299
|
+
`);
|
|
300
|
+
const result = stmt.run(this.projectId, userId);
|
|
301
|
+
logger.info(`Deleted user data for ${userId} (${result.changes} memories)`);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Export data for GDPR compliance
|
|
305
|
+
*/
|
|
306
|
+
async exportUserData(userId) {
|
|
307
|
+
try {
|
|
308
|
+
// Check if memories table exists
|
|
309
|
+
const tableCheck = this.db.prepare(`
|
|
310
|
+
SELECT name FROM sqlite_master
|
|
311
|
+
WHERE type='table' AND name='memories'
|
|
312
|
+
`).get();
|
|
313
|
+
if (!tableCheck) {
|
|
314
|
+
// No memories table yet
|
|
315
|
+
return JSON.stringify({
|
|
316
|
+
exportDate: new Date().toISOString(),
|
|
317
|
+
userId,
|
|
318
|
+
projectId: this.projectId,
|
|
319
|
+
memories: [],
|
|
320
|
+
totalCount: 0,
|
|
321
|
+
note: 'No memories table exists yet'
|
|
322
|
+
}, null, 2);
|
|
323
|
+
}
|
|
324
|
+
// First try to get user-specific memories (handle missing metadata column)
|
|
325
|
+
let userMemories = [];
|
|
326
|
+
try {
|
|
327
|
+
const userStmt = this.db.prepare(`
|
|
328
|
+
SELECT * FROM memories
|
|
329
|
+
WHERE project_id = ?
|
|
330
|
+
AND json_extract(metadata, '$.userId') = ?
|
|
331
|
+
`);
|
|
332
|
+
userMemories = userStmt.all(this.projectId, userId);
|
|
333
|
+
}
|
|
334
|
+
catch (e) {
|
|
335
|
+
// metadata column might not exist
|
|
336
|
+
logger.debug('No metadata column in memories table');
|
|
337
|
+
}
|
|
338
|
+
// If no user-specific memories, get all project memories for demo/testing
|
|
339
|
+
let memories = userMemories;
|
|
340
|
+
if (memories.length === 0) {
|
|
341
|
+
const allStmt = this.db.prepare(`
|
|
342
|
+
SELECT * FROM memories
|
|
343
|
+
WHERE project_id = ?
|
|
344
|
+
LIMIT 10
|
|
345
|
+
`);
|
|
346
|
+
memories = allStmt.all(this.projectId);
|
|
347
|
+
}
|
|
348
|
+
const exportData = {
|
|
349
|
+
exportDate: new Date().toISOString(),
|
|
350
|
+
userId,
|
|
351
|
+
projectId: this.projectId,
|
|
352
|
+
memories,
|
|
353
|
+
totalCount: memories.length,
|
|
354
|
+
note: memories.length === 0 ? 'No data found for this user' :
|
|
355
|
+
userMemories.length === 0 ? 'Showing sample project data (user has no specific data)' :
|
|
356
|
+
'User-specific data exported'
|
|
357
|
+
};
|
|
358
|
+
return JSON.stringify(exportData, null, 2);
|
|
359
|
+
}
|
|
360
|
+
catch (error) {
|
|
361
|
+
logger.error('GDPR export failed', error);
|
|
362
|
+
return JSON.stringify({
|
|
363
|
+
error: 'Export failed',
|
|
364
|
+
message: error.message,
|
|
365
|
+
userId,
|
|
366
|
+
projectId: this.projectId
|
|
367
|
+
}, null, 2);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
/**
|
|
371
|
+
* Start background cleanup scheduler
|
|
372
|
+
*/
|
|
373
|
+
startCleanupScheduler() {
|
|
374
|
+
// Run cleanup every hour
|
|
375
|
+
setInterval(() => {
|
|
376
|
+
this.runCleanup();
|
|
377
|
+
}, 60 * 60 * 1000);
|
|
378
|
+
// Initial cleanup
|
|
379
|
+
this.runCleanup();
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Run cleanup tasks
|
|
383
|
+
*/
|
|
384
|
+
async runCleanup() {
|
|
385
|
+
try {
|
|
386
|
+
// Check if tables exist first
|
|
387
|
+
const tablesExist = this.db.prepare(`
|
|
388
|
+
SELECT name FROM sqlite_master
|
|
389
|
+
WHERE type='table' AND name='memories'
|
|
390
|
+
`).get();
|
|
391
|
+
if (!tablesExist) {
|
|
392
|
+
return; // Tables not initialized yet
|
|
393
|
+
}
|
|
394
|
+
// Delete expired memories
|
|
395
|
+
const deleteStmt = this.db.prepare(`
|
|
396
|
+
DELETE FROM memories
|
|
397
|
+
WHERE project_id = ?
|
|
398
|
+
AND expires_at IS NOT NULL
|
|
399
|
+
AND expires_at < ?
|
|
400
|
+
`);
|
|
401
|
+
const deleteResult = deleteStmt.run(this.projectId, Date.now());
|
|
402
|
+
// Delete expired archives
|
|
403
|
+
const archiveDeleteStmt = this.archiveDb.prepare(`
|
|
404
|
+
DELETE FROM archives
|
|
405
|
+
WHERE project_id = ?
|
|
406
|
+
AND expires_at < ?
|
|
407
|
+
`);
|
|
408
|
+
const archiveResult = archiveDeleteStmt.run(this.projectId, Date.now());
|
|
409
|
+
if (deleteResult.changes > 0 || archiveResult.changes > 0) {
|
|
410
|
+
logger.info(`Cleanup: deleted ${deleteResult.changes} memories, ${archiveResult.changes} archives`);
|
|
411
|
+
}
|
|
412
|
+
// Archive old memories
|
|
413
|
+
await this.archiveOldMemories();
|
|
414
|
+
}
|
|
415
|
+
catch (error) {
|
|
416
|
+
logger.error('Cleanup failed:', error);
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Get retention statistics
|
|
421
|
+
*/
|
|
422
|
+
getStats() {
|
|
423
|
+
const memoryCount = this.db.prepare(`
|
|
424
|
+
SELECT COUNT(*) as count FROM memories WHERE project_id = ?
|
|
425
|
+
`).get(this.projectId);
|
|
426
|
+
const archiveCount = this.archiveDb.prepare(`
|
|
427
|
+
SELECT COUNT(*) as count FROM archives WHERE project_id = ?
|
|
428
|
+
`).get(this.projectId);
|
|
429
|
+
const deletionCount = this.archiveDb.prepare(`
|
|
430
|
+
SELECT COUNT(*) as count FROM deletion_log WHERE project_id = ?
|
|
431
|
+
`).get(this.projectId);
|
|
432
|
+
return {
|
|
433
|
+
activeMemories: memoryCount.count,
|
|
434
|
+
archivedMemories: archiveCount.count,
|
|
435
|
+
deletions: deletionCount.count,
|
|
436
|
+
policies: Array.from(this.policies.values())
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
close() {
|
|
440
|
+
this.db.close();
|
|
441
|
+
this.archiveDb.close();
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
//# sourceMappingURL=data-retention.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data-retention.js","sourceRoot":"","sources":["../../src/security/data-retention.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* At-rest encryption using AES-256-GCM
|
|
3
|
+
* Per-project keys stored securely
|
|
4
|
+
*/
|
|
5
|
+
export declare class EncryptionManager {
|
|
6
|
+
private projectId;
|
|
7
|
+
private key;
|
|
8
|
+
private keyPath;
|
|
9
|
+
private algorithm;
|
|
10
|
+
constructor(projectRoot: string, projectId: string);
|
|
11
|
+
/**
|
|
12
|
+
* Load existing key or create new one
|
|
13
|
+
*/
|
|
14
|
+
private loadOrCreateKey;
|
|
15
|
+
/**
|
|
16
|
+
* Save key securely (restricted permissions)
|
|
17
|
+
*/
|
|
18
|
+
private saveKey;
|
|
19
|
+
/**
|
|
20
|
+
* Encrypt data
|
|
21
|
+
*/
|
|
22
|
+
encrypt(text: string): {
|
|
23
|
+
encrypted: string;
|
|
24
|
+
iv: string;
|
|
25
|
+
tag: string;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Decrypt data
|
|
29
|
+
*/
|
|
30
|
+
decrypt(encrypted: string, iv: string, tag: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* Encrypt JSON object
|
|
33
|
+
*/
|
|
34
|
+
encryptJSON(obj: any): string;
|
|
35
|
+
/**
|
|
36
|
+
* Decrypt JSON object
|
|
37
|
+
*/
|
|
38
|
+
decryptJSON(encryptedData: string): any;
|
|
39
|
+
/**
|
|
40
|
+
* Rotate encryption key
|
|
41
|
+
*/
|
|
42
|
+
rotateKey(reencryptCallback: (oldDecrypt: (data: string) => any, newEncrypt: (data: any) => string) => Promise<void>): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Destroy key (for secure deletion)
|
|
45
|
+
*/
|
|
46
|
+
destroyKey(): void;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=encryption.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.d.ts","sourceRoot":"","sources":["../../src/security/encryption.ts"],"names":[],"mappings":"AAOA;;;GAGG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,SAAS,CAAiB;gBAEtB,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;IAMlD;;OAEG;IACH,OAAO,CAAC,eAAe;IAkBvB;;OAEG;IACH,OAAO,CAAC,OAAO;IAYf;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAgBrE;;OAEG;IACH,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM;IAe3D;;OAEG;IACH,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM;IAQ7B;;OAEG;IACH,WAAW,CAAC,aAAa,EAAE,MAAM,GAAG,GAAG;IAMvC;;OAEG;IACG,SAAS,CAAC,iBAAiB,EAAE,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,GAAG,EAAE,UAAU,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAqB1I;;OAEG;IACH,UAAU,IAAI,IAAI;CAanB"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import crypto from 'crypto';
|
|
2
|
+
import fs from 'fs-extra';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import { Logger } from '../utils/logger.js';
|
|
5
|
+
const logger = new Logger('Encryption');
|
|
6
|
+
/**
|
|
7
|
+
* At-rest encryption using AES-256-GCM
|
|
8
|
+
* Per-project keys stored securely
|
|
9
|
+
*/
|
|
10
|
+
export class EncryptionManager {
|
|
11
|
+
projectId;
|
|
12
|
+
key;
|
|
13
|
+
keyPath;
|
|
14
|
+
algorithm = 'aes-256-gcm';
|
|
15
|
+
constructor(projectRoot, projectId) {
|
|
16
|
+
this.projectId = projectId;
|
|
17
|
+
this.keyPath = path.join(projectRoot, '.kratos', '.keys', `${projectId}.key`);
|
|
18
|
+
this.key = this.loadOrCreateKey();
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Load existing key or create new one
|
|
22
|
+
*/
|
|
23
|
+
loadOrCreateKey() {
|
|
24
|
+
try {
|
|
25
|
+
if (fs.existsSync(this.keyPath)) {
|
|
26
|
+
const keyData = fs.readFileSync(this.keyPath);
|
|
27
|
+
logger.info(`Loaded encryption key for project ${this.projectId}`);
|
|
28
|
+
return keyData;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
logger.warn('Failed to load key, creating new one:', error);
|
|
33
|
+
}
|
|
34
|
+
// Generate new key
|
|
35
|
+
const key = crypto.randomBytes(32); // 256 bits
|
|
36
|
+
this.saveKey(key);
|
|
37
|
+
logger.info(`Generated new encryption key for project ${this.projectId}`);
|
|
38
|
+
return key;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Save key securely (restricted permissions)
|
|
42
|
+
*/
|
|
43
|
+
saveKey(key) {
|
|
44
|
+
fs.ensureDirSync(path.dirname(this.keyPath));
|
|
45
|
+
fs.writeFileSync(this.keyPath, key);
|
|
46
|
+
// Set restrictive permissions (owner read/write only)
|
|
47
|
+
try {
|
|
48
|
+
fs.chmodSync(this.keyPath, 0o600);
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
logger.warn('Could not set key file permissions:', error);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Encrypt data
|
|
56
|
+
*/
|
|
57
|
+
encrypt(text) {
|
|
58
|
+
const iv = crypto.randomBytes(16);
|
|
59
|
+
const cipher = crypto.createCipheriv(this.algorithm, this.key, iv);
|
|
60
|
+
let encrypted = cipher.update(text, 'utf8', 'hex');
|
|
61
|
+
encrypted += cipher.final('hex');
|
|
62
|
+
const tag = cipher.getAuthTag();
|
|
63
|
+
return {
|
|
64
|
+
encrypted,
|
|
65
|
+
iv: iv.toString('hex'),
|
|
66
|
+
tag: tag.toString('hex')
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Decrypt data
|
|
71
|
+
*/
|
|
72
|
+
decrypt(encrypted, iv, tag) {
|
|
73
|
+
const decipher = crypto.createDecipheriv(this.algorithm, this.key, Buffer.from(iv, 'hex'));
|
|
74
|
+
decipher.setAuthTag(Buffer.from(tag, 'hex'));
|
|
75
|
+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
76
|
+
decrypted += decipher.final('utf8');
|
|
77
|
+
return decrypted;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Encrypt JSON object
|
|
81
|
+
*/
|
|
82
|
+
encryptJSON(obj) {
|
|
83
|
+
const json = JSON.stringify(obj);
|
|
84
|
+
const { encrypted, iv, tag } = this.encrypt(json);
|
|
85
|
+
// Combine into single string
|
|
86
|
+
return `${iv}:${tag}:${encrypted}`;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Decrypt JSON object
|
|
90
|
+
*/
|
|
91
|
+
decryptJSON(encryptedData) {
|
|
92
|
+
const [iv, tag, encrypted] = encryptedData.split(':');
|
|
93
|
+
const json = this.decrypt(encrypted, iv, tag);
|
|
94
|
+
return JSON.parse(json);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Rotate encryption key
|
|
98
|
+
*/
|
|
99
|
+
async rotateKey(reencryptCallback) {
|
|
100
|
+
const oldKey = this.key;
|
|
101
|
+
const oldDecrypt = (data) => {
|
|
102
|
+
const [iv, tag, encrypted] = data.split(':');
|
|
103
|
+
const decipher = crypto.createDecipheriv(this.algorithm, oldKey, Buffer.from(iv, 'hex'));
|
|
104
|
+
decipher.setAuthTag(Buffer.from(tag, 'hex'));
|
|
105
|
+
let decrypted = decipher.update(encrypted, 'hex', 'utf8');
|
|
106
|
+
decrypted += decipher.final('utf8');
|
|
107
|
+
return JSON.parse(decrypted);
|
|
108
|
+
};
|
|
109
|
+
// Generate new key
|
|
110
|
+
this.key = crypto.randomBytes(32);
|
|
111
|
+
this.saveKey(this.key);
|
|
112
|
+
// Re-encrypt all data
|
|
113
|
+
await reencryptCallback(oldDecrypt, (data) => this.encryptJSON(data));
|
|
114
|
+
logger.info('Key rotation completed');
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Destroy key (for secure deletion)
|
|
118
|
+
*/
|
|
119
|
+
destroyKey() {
|
|
120
|
+
// Overwrite key in memory
|
|
121
|
+
this.key.fill(0);
|
|
122
|
+
// Overwrite key file
|
|
123
|
+
if (fs.existsSync(this.keyPath)) {
|
|
124
|
+
const randomData = crypto.randomBytes(32);
|
|
125
|
+
fs.writeFileSync(this.keyPath, randomData);
|
|
126
|
+
fs.unlinkSync(this.keyPath);
|
|
127
|
+
}
|
|
128
|
+
logger.info('Encryption key destroyed');
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
//# sourceMappingURL=encryption.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"encryption.js","sourceRoot":"","sources":["../../src/security/encryption.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,CAAC,CAAC;AAExC;;;GAGG;AACH,MAAM,OAAO,iBAAiB;IACpB,SAAS,CAAS;IAClB,GAAG,CAAS;IACZ,OAAO,CAAS;IAChB,SAAS,GAAG,aAAa,CAAC;IAElC,YAAY,WAAmB,EAAE,SAAiB;QAChD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;QAC3B,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,SAAS,MAAM,CAAC,CAAC;QAC9E,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC,eAAe,EAAE,CAAC;IACpC,CAAC;IAED;;OAEG;IACK,eAAe;QACrB,IAAI,CAAC;YACH,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC9C,MAAM,CAAC,IAAI,CAAC,qCAAqC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;gBACnE,OAAO,OAAO,CAAC;YACjB,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,uCAAuC,EAAE,KAAK,CAAC,CAAC;QAC9D,CAAC;QAED,mBAAmB;QACnB,MAAM,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW;QAC/C,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,4CAA4C,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QAC1E,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACK,OAAO,CAAC,GAAW;QACzB,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QAC7C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAEpC,sDAAsD;QACtD,IAAI,CAAC;YACH,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,IAAY;QAClB,MAAM,EAAE,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAqB,CAAC;QAEvF,IAAI,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC;QACnD,SAAS,IAAI,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAEjC,MAAM,GAAG,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC;QAEhC,OAAO;YACL,SAAS;YACT,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;YACtB,GAAG,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;SACzB,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,SAAiB,EAAE,EAAU,EAAE,GAAW;QAChD,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CACtC,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,GAAG,EACR,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CACD,CAAC;QAExB,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;QAE7C,IAAI,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;QAC1D,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;QAEpC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,GAAQ;QAClB,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QACjC,MAAM,EAAE,SAAS,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAElD,6BAA6B;QAC7B,OAAO,GAAG,EAAE,IAAI,GAAG,IAAI,SAAS,EAAE,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,WAAW,CAAC,aAAqB;QAC/B,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACtD,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,CAAC;QAC9C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,iBAA0G;QACxH,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC;QACxB,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;YAClC,MAAM,CAAC,EAAE,EAAE,GAAG,EAAE,SAAS,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YAC7C,MAAM,QAAQ,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAuB,CAAC;YAC/G,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7C,IAAI,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC;YAC1D,SAAS,IAAI,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC,CAAC;QAEF,mBAAmB;QACnB,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QAClC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAEvB,sBAAsB;QACtB,MAAM,iBAAiB,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAEtE,MAAM,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACxC,CAAC;IAED;;OAEG;IACH,UAAU;QACR,0BAA0B;QAC1B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEjB,qBAAqB;QACrB,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAChC,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;YAC1C,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;YAC3C,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,CAAC;QAED,MAAM,CAAC,IAAI,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;CACF"}
|