@tamyla/clodo-framework 3.1.10 → 3.1.12
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/CHANGELOG.md +14 -0
- package/dist/bin/clodo-service-old.js +2 -2
- package/dist/bin/commands/create.js +1 -1
- package/dist/bin/commands/diagnose.js +1 -1
- package/dist/bin/commands/update.js +1 -1
- package/dist/bin/commands/validate.js +1 -1
- package/dist/bin/database/enterprise-db-manager.js +3 -3
- package/dist/bin/deployment/enterprise-deploy.js +3 -3
- package/dist/bin/deployment/master-deploy.js +3 -3
- package/dist/bin/deployment/modular-enterprise-deploy.js +3 -3
- package/dist/bin/deployment/modules/DeploymentOrchestrator.js +1 -1
- package/dist/bin/deployment/modules/EnvironmentManager.js +2 -2
- package/dist/bin/portfolio/portfolio-manager.js +3 -3
- package/dist/bin/security/security-cli.js +1 -1
- package/dist/bin/service-management/create-service.js +1 -1
- package/dist/bin/service-management/init-service.js +1 -1
- package/dist/bin/shared/cloudflare/domain-manager.js +1 -1
- package/dist/bin/shared/validation/ValidationRegistry.js +1 -1
- package/dist/deployment/wrangler-deployer.js +1 -1
- package/dist/orchestration/cross-domain-coordinator.js +5 -5
- package/dist/security/index.js +1 -1
- package/dist/service-management/ConfirmationEngine.js +1 -1
- package/dist/service-management/ErrorTracker.js +1 -1
- package/dist/service-management/InputCollector.js +1 -1
- package/dist/service-management/ServiceCreator.js +1 -1
- package/dist/service-management/ServiceInitializer.js +1 -1
- package/dist/utils/config/unified-config-manager.js +1 -1
- package/dist/utils/deployment/config-cache.js +1 -1
- package/dist/utils/deployment/secret-generator.js +1 -1
- package/dist/utils/framework-config.js +1 -1
- package/dist/worker/integration.js +1 -1
- package/package.json +1 -6
- package/bin/README.md +0 -71
- package/bin/clodo-service.js +0 -72
- package/bin/database/README.md +0 -33
- package/bin/database/deployment-db-manager.js +0 -527
- package/bin/database/enterprise-db-manager.js +0 -738
- package/bin/database/wrangler-d1-manager.js +0 -775
- package/bin/security/security-cli.js +0 -117
- package/bin/service-management/README.md +0 -74
- package/bin/service-management/create-service.js +0 -129
- package/bin/service-management/init-service.js +0 -103
- package/bin/service-management/init-service.js.backup +0 -889
- package/bin/shared/cloudflare/domain-discovery.js +0 -637
- package/bin/shared/cloudflare/domain-manager.js +0 -952
- package/bin/shared/cloudflare/index.js +0 -8
- package/bin/shared/cloudflare/ops.js +0 -401
- package/bin/shared/config/ConfigurationManager.js +0 -539
- package/bin/shared/config/cache.js +0 -1230
- package/bin/shared/config/command-config-manager.js +0 -184
- package/bin/shared/config/index.js +0 -21
- package/bin/shared/config/manager.js +0 -315
- package/bin/shared/database/connection-manager.js +0 -374
- package/bin/shared/database/index.js +0 -7
- package/bin/shared/database/orchestrator.js +0 -727
- package/bin/shared/deployment/auditor.js +0 -970
- package/bin/shared/deployment/index.js +0 -10
- package/bin/shared/deployment/rollback-manager.js +0 -570
- package/bin/shared/deployment/validator.js +0 -779
- package/bin/shared/index.js +0 -32
- package/bin/shared/logging/Logger.js +0 -214
- package/bin/shared/monitoring/health-checker.js +0 -484
- package/bin/shared/monitoring/index.js +0 -8
- package/bin/shared/monitoring/memory-manager.js +0 -387
- package/bin/shared/monitoring/production-monitor.js +0 -403
- package/bin/shared/production-tester/api-tester.js +0 -82
- package/bin/shared/production-tester/auth-tester.js +0 -132
- package/bin/shared/production-tester/core.js +0 -197
- package/bin/shared/production-tester/database-tester.js +0 -109
- package/bin/shared/production-tester/index.js +0 -77
- package/bin/shared/production-tester/load-tester.js +0 -131
- package/bin/shared/production-tester/performance-tester.js +0 -103
- package/bin/shared/security/api-token-manager.js +0 -312
- package/bin/shared/security/index.js +0 -8
- package/bin/shared/security/secret-generator.js +0 -942
- package/bin/shared/security/secure-token-manager.js +0 -398
- package/bin/shared/utils/ErrorHandler.js +0 -675
- package/bin/shared/utils/error-recovery.js +0 -245
- package/bin/shared/utils/file-manager.js +0 -162
- package/bin/shared/utils/formatters.js +0 -247
- package/bin/shared/utils/graceful-shutdown-manager.js +0 -390
- package/bin/shared/utils/index.js +0 -19
- package/bin/shared/utils/interactive-prompts.js +0 -146
- package/bin/shared/utils/interactive-utils.js +0 -530
- package/bin/shared/utils/rate-limiter.js +0 -246
- package/bin/shared/validation/ValidationRegistry.js +0 -143
|
@@ -1,398 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Secure Token Manager
|
|
3
|
-
* Implements secure token storage, rotation, and access control
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import { readFile, writeFile, access, mkdir } from 'fs/promises';
|
|
7
|
-
import { join } from 'path';
|
|
8
|
-
import { exec } from 'child_process';
|
|
9
|
-
import { promisify } from 'util';
|
|
10
|
-
import crypto from 'crypto';
|
|
11
|
-
|
|
12
|
-
const execAsync = promisify(exec);
|
|
13
|
-
|
|
14
|
-
export class SecureTokenManager {
|
|
15
|
-
constructor(options = {}) {
|
|
16
|
-
this.frameworkConfig = null; // Will be loaded in initialize()
|
|
17
|
-
this.config = {
|
|
18
|
-
tokenDir: options.tokenDir, // Will be set from framework config if not provided
|
|
19
|
-
encryptionKey: options.encryptionKey || this.generateEncryptionKey(),
|
|
20
|
-
tokenRotationInterval: options.tokenRotationInterval || 24 * 60 * 60 * 1000, // 24 hours
|
|
21
|
-
maxTokensPerService: options.maxTokensPerService || 3,
|
|
22
|
-
enableAudit: options.enableAudit !== false,
|
|
23
|
-
auditLogPath: options.auditLogPath, // Will be set from framework config if not provided
|
|
24
|
-
...options
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
this.tokens = new Map(); // service -> token data
|
|
28
|
-
this.auditLog = [];
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Initialize the token manager
|
|
33
|
-
*/
|
|
34
|
-
async initialize() {
|
|
35
|
-
try {
|
|
36
|
-
// Load framework configuration
|
|
37
|
-
const { frameworkConfig } = await import('../../../dist/utils/framework-config.js');
|
|
38
|
-
this.frameworkConfig = frameworkConfig;
|
|
39
|
-
|
|
40
|
-
// Update paths with framework config
|
|
41
|
-
const configPaths = this.frameworkConfig.getPaths();
|
|
42
|
-
|
|
43
|
-
this.config.tokenDir = this.config.tokenDir || configPaths.secureTokens;
|
|
44
|
-
this.config.auditLogPath = this.config.auditLogPath || join(configPaths.auditLogs, 'token-audit.log');
|
|
45
|
-
|
|
46
|
-
console.log(`🔐 Token directory configured: ${this.config.tokenDir}`);
|
|
47
|
-
console.log(`📋 Token audit log: ${this.config.auditLogPath}`);
|
|
48
|
-
|
|
49
|
-
} catch (error) {
|
|
50
|
-
console.warn(`⚠️ Could not load framework config: ${error.message}. Using default paths.`);
|
|
51
|
-
// Use fallback defaults
|
|
52
|
-
this.config.tokenDir = this.config.tokenDir || '.secure-tokens';
|
|
53
|
-
this.config.auditLogPath = this.config.auditLogPath || 'token-audit.log';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
await this.ensureSecureDirectory();
|
|
57
|
-
await this.loadTokens();
|
|
58
|
-
await this.rotateExpiredTokens();
|
|
59
|
-
|
|
60
|
-
if (this.config.enableAudit) {
|
|
61
|
-
this.logAuditEvent('TOKEN_MANAGER_INITIALIZED', { timestamp: new Date() });
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Store a token securely
|
|
67
|
-
*/
|
|
68
|
-
async storeToken(service, token, metadata = {}) {
|
|
69
|
-
const tokenData = {
|
|
70
|
-
service,
|
|
71
|
-
token: this.encrypt(token),
|
|
72
|
-
created: new Date(),
|
|
73
|
-
expires: new Date(Date.now() + this.config.tokenRotationInterval),
|
|
74
|
-
metadata: {
|
|
75
|
-
...metadata,
|
|
76
|
-
permissions: metadata.permissions || ['read'],
|
|
77
|
-
environment: metadata.environment || 'production'
|
|
78
|
-
},
|
|
79
|
-
fingerprint: this.generateFingerprint(token)
|
|
80
|
-
};
|
|
81
|
-
|
|
82
|
-
// Check token limits
|
|
83
|
-
const serviceTokens = this.getServiceTokens(service);
|
|
84
|
-
if (serviceTokens.length >= this.config.maxTokensPerService) {
|
|
85
|
-
// Remove oldest token
|
|
86
|
-
const oldestToken = serviceTokens.sort((a, b) => a.created - b.created)[0];
|
|
87
|
-
await this.revokeToken(service, oldestToken.fingerprint);
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
this.tokens.set(`${service}_${tokenData.fingerprint}`, tokenData);
|
|
91
|
-
await this.saveTokens();
|
|
92
|
-
|
|
93
|
-
if (this.config.enableAudit) {
|
|
94
|
-
this.logAuditEvent('TOKEN_STORED', {
|
|
95
|
-
service,
|
|
96
|
-
fingerprint: tokenData.fingerprint,
|
|
97
|
-
permissions: tokenData.metadata.permissions
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
return tokenData.fingerprint;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Retrieve a token securely
|
|
106
|
-
*/
|
|
107
|
-
async retrieveToken(service, fingerprint, requiredPermissions = []) {
|
|
108
|
-
const tokenKey = `${service}_${fingerprint}`;
|
|
109
|
-
const tokenData = this.tokens.get(tokenKey);
|
|
110
|
-
|
|
111
|
-
if (!tokenData) {
|
|
112
|
-
throw new Error(`Token not found for service: ${service}`);
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Check expiration
|
|
116
|
-
if (new Date() > tokenData.expires) {
|
|
117
|
-
await this.revokeToken(service, fingerprint);
|
|
118
|
-
throw new Error(`Token expired for service: ${service}`);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Check permissions
|
|
122
|
-
if (requiredPermissions.length > 0) {
|
|
123
|
-
const hasPermissions = requiredPermissions.every(perm =>
|
|
124
|
-
tokenData.metadata.permissions.includes(perm)
|
|
125
|
-
);
|
|
126
|
-
if (!hasPermissions) {
|
|
127
|
-
if (this.config.enableAudit) {
|
|
128
|
-
this.logAuditEvent('TOKEN_ACCESS_DENIED', {
|
|
129
|
-
service,
|
|
130
|
-
fingerprint,
|
|
131
|
-
requiredPermissions,
|
|
132
|
-
tokenPermissions: tokenData.metadata.permissions
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
throw new Error(`Insufficient permissions for token access`);
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (this.config.enableAudit) {
|
|
140
|
-
this.logAuditEvent('TOKEN_RETRIEVED', {
|
|
141
|
-
service,
|
|
142
|
-
fingerprint,
|
|
143
|
-
permissions: tokenData.metadata.permissions
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return this.decrypt(tokenData.token);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
/**
|
|
151
|
-
* Rotate a token
|
|
152
|
-
*/
|
|
153
|
-
async rotateToken(service, fingerprint, newToken) {
|
|
154
|
-
const tokenKey = `${service}_${fingerprint}`;
|
|
155
|
-
const tokenData = this.tokens.get(tokenKey);
|
|
156
|
-
|
|
157
|
-
if (!tokenData) {
|
|
158
|
-
throw new Error(`Token not found for rotation: ${service}`);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
const newFingerprint = this.generateFingerprint(newToken);
|
|
162
|
-
const rotatedTokenData = {
|
|
163
|
-
...tokenData,
|
|
164
|
-
token: this.encrypt(newToken),
|
|
165
|
-
created: new Date(),
|
|
166
|
-
expires: new Date(Date.now() + this.config.tokenRotationInterval),
|
|
167
|
-
fingerprint: newFingerprint,
|
|
168
|
-
rotatedFrom: fingerprint
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
// Remove old token
|
|
172
|
-
this.tokens.delete(tokenKey);
|
|
173
|
-
|
|
174
|
-
// Store new token
|
|
175
|
-
this.tokens.set(`${service}_${newFingerprint}`, rotatedTokenData);
|
|
176
|
-
await this.saveTokens();
|
|
177
|
-
|
|
178
|
-
if (this.config.enableAudit) {
|
|
179
|
-
this.logAuditEvent('TOKEN_ROTATED', {
|
|
180
|
-
service,
|
|
181
|
-
oldFingerprint: fingerprint,
|
|
182
|
-
newFingerprint: newFingerprint
|
|
183
|
-
});
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
return newFingerprint;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
/**
|
|
190
|
-
* Revoke a token
|
|
191
|
-
*/
|
|
192
|
-
async revokeToken(service, fingerprint) {
|
|
193
|
-
const tokenKey = `${service}_${fingerprint}`;
|
|
194
|
-
const tokenData = this.tokens.get(tokenKey);
|
|
195
|
-
|
|
196
|
-
if (tokenData) {
|
|
197
|
-
this.tokens.delete(tokenKey);
|
|
198
|
-
await this.saveTokens();
|
|
199
|
-
|
|
200
|
-
if (this.config.enableAudit) {
|
|
201
|
-
this.logAuditEvent('TOKEN_REVOKED', {
|
|
202
|
-
service,
|
|
203
|
-
fingerprint,
|
|
204
|
-
reason: 'manual_revoke'
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
/**
|
|
211
|
-
* List tokens for a service
|
|
212
|
-
*/
|
|
213
|
-
listTokens(service) {
|
|
214
|
-
const serviceTokens = [];
|
|
215
|
-
for (const [key, tokenData] of this.tokens) {
|
|
216
|
-
if (key.startsWith(`${service}_`)) {
|
|
217
|
-
serviceTokens.push({
|
|
218
|
-
fingerprint: tokenData.fingerprint,
|
|
219
|
-
created: tokenData.created,
|
|
220
|
-
expires: tokenData.expires,
|
|
221
|
-
permissions: tokenData.metadata.permissions,
|
|
222
|
-
environment: tokenData.metadata.environment
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
return serviceTokens;
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
/**
|
|
230
|
-
* Get service tokens
|
|
231
|
-
*/
|
|
232
|
-
getServiceTokens(service) {
|
|
233
|
-
const serviceTokens = [];
|
|
234
|
-
for (const [key, tokenData] of this.tokens) {
|
|
235
|
-
if (key.startsWith(`${service}_`)) {
|
|
236
|
-
serviceTokens.push(tokenData);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
return serviceTokens;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
/**
|
|
243
|
-
* Rotate expired tokens
|
|
244
|
-
*/
|
|
245
|
-
async rotateExpiredTokens() {
|
|
246
|
-
const now = new Date();
|
|
247
|
-
const expiredTokens = [];
|
|
248
|
-
|
|
249
|
-
for (const [key, tokenData] of this.tokens) {
|
|
250
|
-
if (now > tokenData.expires) {
|
|
251
|
-
expiredTokens.push({ key, tokenData });
|
|
252
|
-
}
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
for (const { key, tokenData } of expiredTokens) {
|
|
256
|
-
this.tokens.delete(key);
|
|
257
|
-
if (this.config.enableAudit) {
|
|
258
|
-
this.logAuditEvent('TOKEN_EXPIRED', {
|
|
259
|
-
service: tokenData.service,
|
|
260
|
-
fingerprint: tokenData.fingerprint
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
if (expiredTokens.length > 0) {
|
|
266
|
-
await this.saveTokens();
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
/**
|
|
271
|
-
* Encrypt token data
|
|
272
|
-
*/
|
|
273
|
-
encrypt(data) {
|
|
274
|
-
const iv = crypto.randomBytes(16);
|
|
275
|
-
const cipher = crypto.createCipher('aes-256-gcm', this.config.encryptionKey);
|
|
276
|
-
cipher.setIV(iv);
|
|
277
|
-
|
|
278
|
-
let encrypted = cipher.update(data, 'utf8', 'hex');
|
|
279
|
-
encrypted += cipher.final('hex');
|
|
280
|
-
|
|
281
|
-
const authTag = cipher.getAuthTag();
|
|
282
|
-
|
|
283
|
-
return {
|
|
284
|
-
encrypted,
|
|
285
|
-
iv: iv.toString('hex'),
|
|
286
|
-
authTag: authTag.toString('hex')
|
|
287
|
-
};
|
|
288
|
-
}
|
|
289
|
-
|
|
290
|
-
/**
|
|
291
|
-
* Decrypt token data
|
|
292
|
-
*/
|
|
293
|
-
decrypt(encryptedData) {
|
|
294
|
-
const decipher = crypto.createDecipher('aes-256-gcm', this.config.encryptionKey);
|
|
295
|
-
decipher.setIV(Buffer.from(encryptedData.iv, 'hex'));
|
|
296
|
-
decipher.setAuthTag(Buffer.from(encryptedData.authTag, 'hex'));
|
|
297
|
-
|
|
298
|
-
let decrypted = decipher.update(encryptedData.encrypted, 'hex', 'utf8');
|
|
299
|
-
decrypted += decipher.final('utf8');
|
|
300
|
-
|
|
301
|
-
return decrypted;
|
|
302
|
-
}
|
|
303
|
-
|
|
304
|
-
/**
|
|
305
|
-
* Generate encryption key
|
|
306
|
-
*/
|
|
307
|
-
generateEncryptionKey() {
|
|
308
|
-
return crypto.randomBytes(32).toString('hex');
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
/**
|
|
312
|
-
* Generate token fingerprint
|
|
313
|
-
*/
|
|
314
|
-
generateFingerprint(token) {
|
|
315
|
-
return crypto.createHash('sha256').update(token).digest('hex').substring(0, 16);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Ensure secure directory exists
|
|
320
|
-
*/
|
|
321
|
-
async ensureSecureDirectory() {
|
|
322
|
-
try {
|
|
323
|
-
await access(this.config.tokenDir);
|
|
324
|
-
} catch {
|
|
325
|
-
await mkdir(this.config.tokenDir, { mode: 0o700 }); // Secure permissions
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
/**
|
|
330
|
-
* Save tokens to disk
|
|
331
|
-
*/
|
|
332
|
-
async saveTokens() {
|
|
333
|
-
const tokenFile = join(this.config.tokenDir, 'tokens.json');
|
|
334
|
-
const tokenData = {};
|
|
335
|
-
|
|
336
|
-
for (const [key, token] of this.tokens) {
|
|
337
|
-
tokenData[key] = token;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
await writeFile(tokenFile, JSON.stringify(tokenData, null, 2));
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Load tokens from disk
|
|
345
|
-
*/
|
|
346
|
-
async loadTokens() {
|
|
347
|
-
try {
|
|
348
|
-
const tokenFile = join(this.config.tokenDir, 'tokens.json');
|
|
349
|
-
const data = await readFile(tokenFile, 'utf8');
|
|
350
|
-
const tokenData = JSON.parse(data);
|
|
351
|
-
|
|
352
|
-
for (const [key, token] of Object.entries(tokenData)) {
|
|
353
|
-
// Convert date strings back to Date objects
|
|
354
|
-
token.created = new Date(token.created);
|
|
355
|
-
token.expires = new Date(token.expires);
|
|
356
|
-
this.tokens.set(key, token);
|
|
357
|
-
}
|
|
358
|
-
} catch (error) {
|
|
359
|
-
// File doesn't exist or is corrupted, start fresh
|
|
360
|
-
this.tokens.clear();
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
/**
|
|
365
|
-
* Log audit event
|
|
366
|
-
*/
|
|
367
|
-
logAuditEvent(event, details) {
|
|
368
|
-
const auditEntry = {
|
|
369
|
-
timestamp: new Date(),
|
|
370
|
-
event,
|
|
371
|
-
details
|
|
372
|
-
};
|
|
373
|
-
|
|
374
|
-
this.auditLog.push(auditEntry);
|
|
375
|
-
|
|
376
|
-
// Keep only last 1000 entries in memory
|
|
377
|
-
if (this.auditLog.length > 1000) {
|
|
378
|
-
this.auditLog.shift();
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
// In a real implementation, you'd write to a secure audit log
|
|
382
|
-
console.log(`[TOKEN_AUDIT] ${event}:`, details);
|
|
383
|
-
}
|
|
384
|
-
|
|
385
|
-
/**
|
|
386
|
-
* Get audit log
|
|
387
|
-
*/
|
|
388
|
-
getAuditLog(limit = 100) {
|
|
389
|
-
return this.auditLog.slice(-limit);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
/**
|
|
393
|
-
* Validate token permissions
|
|
394
|
-
*/
|
|
395
|
-
validatePermissions(tokenPermissions, requiredPermissions) {
|
|
396
|
-
return requiredPermissions.every(perm => tokenPermissions.includes(perm));
|
|
397
|
-
}
|
|
398
|
-
}
|