[grade=A] P1-8: replace 66 console.* calls across 6 remaining files with structured logger

Files changed:
- src/security/crypto-utils.js: 16 calls → log tagged 'crypto'
- src/security/docker-security.js: 15 calls → log tagged 'security'
- src/managers/port-lock-manager.js: 16 calls → log tagged 'portlock'
- src/docker/self-updater.js: 10 calls → log tagged 'updater'
- src/security/event-workers.js: 5 calls → log tagged 'events'
- src/security/keychain-manager.js: 4 calls → log tagged 'keychain'

Fixed 2 bugs found during sweep:
- self-updater.js:161 — arrow expression body had trailing semicolon (SyntaxError)
- port-lock-manager.js:137 — log.error referenced 'port' var out of scope (ReferenceError)

1539/1539 Jest tests pass. All ESLint warnings pre-existing (0 new).
This commit is contained in:
Hermes
2026-08-10 20:23:58 -07:00
parent 191d3340a7
commit 7b04bc1d3c
6 changed files with 72 additions and 71 deletions
+11 -10
View File
@@ -10,6 +10,7 @@
const EventEmitter = require('events'); const EventEmitter = require('events');
const https = require('https'); const https = require('https');
const http = require('http'); const http = require('http');
const { log } = require('../utils/logging');
const fs = require('fs'); const fs = require('fs');
const fsp = require('fs').promises; const fsp = require('fs').promises;
const path = require('path'); const path = require('path');
@@ -86,7 +87,7 @@ class SelfUpdater extends EventEmitter {
start() { start() {
if (!this.config.enabled || this.checkTimer) return; if (!this.config.enabled || this.checkTimer) return;
console.log('[SelfUpdater] Starting auto-update checks every %ds', this.config.checkInterval / 1000); log.info('updater', 'Starting auto-update checks', { intervalMs: this.config.checkInterval });
// First check after a short delay (let server finish startup) // First check after a short delay (let server finish startup)
setTimeout(() => { setTimeout(() => {
@@ -124,7 +125,7 @@ class SelfUpdater extends EventEmitter {
return { version: pkg.version, commit }; return { version: pkg.version, commit };
} catch { /* try next candidate */ } } catch { /* try next candidate */ }
} }
console.error('[SelfUpdater] getLocalVersion failed: no candidate package.json found'); log.error('updater', 'getLocalVersion failed: no candidate package.json found');
return { version: '0.0.0', commit: null }; return { version: '0.0.0', commit: null };
} }
@@ -158,7 +159,7 @@ class SelfUpdater extends EventEmitter {
// Fire-and-forget; the response shouldn't block on the container rebuild. // Fire-and-forget; the response shouldn't block on the container rebuild.
setImmediate(() => { setImmediate(() => {
this._autoCheckAndApply().catch(err => this._autoCheckAndApply().catch(err =>
console.error('[SelfUpdater] %s-triggered update error: %s', triggeredBy, err.message) log.error('updater', err, { triggeredBy })
); );
}); });
return { accepted: true, triggeredBy }; return { accepted: true, triggeredBy };
@@ -174,7 +175,7 @@ class SelfUpdater extends EventEmitter {
try { try {
remote = await this._fetchJson(`${this.config.updateUrl}/version.json`); remote = await this._fetchJson(`${this.config.updateUrl}/version.json`);
} catch (primaryErr) { } catch (primaryErr) {
console.warn('[SelfUpdater] Primary server failed:', primaryErr.message, '— trying mirror'); log.warn('updater', 'Primary server failed, trying mirror', { error: primaryErr.message });
try { try {
remote = await this._fetchJson(`${this.config.mirrorUrl}/version.json`); remote = await this._fetchJson(`${this.config.mirrorUrl}/version.json`);
sourceUrl = this.config.mirrorUrl; sourceUrl = this.config.mirrorUrl;
@@ -240,7 +241,7 @@ class SelfUpdater extends EventEmitter {
try { try {
await this._downloadFile(primaryUrl, tarballPath); await this._downloadFile(primaryUrl, tarballPath);
} catch (dlErr) { } catch (dlErr) {
console.warn('[SelfUpdater] Primary download failed:', dlErr.message, '— trying mirror'); log.warn('updater', 'Primary download failed, trying mirror', { error: dlErr.message });
// Ensure file is fully cleaned up before mirror attempt // Ensure file is fully cleaned up before mirror attempt
try { fs.unlinkSync(tarballPath); } catch { /* ignore */ } try { fs.unlinkSync(tarballPath); } catch { /* ignore */ }
await this._downloadFile(mirrorUrl, tarballPath); await this._downloadFile(mirrorUrl, tarballPath);
@@ -468,11 +469,11 @@ class SelfUpdater extends EventEmitter {
try { try {
const result = await this.checkForUpdate(); const result = await this.checkForUpdate();
if (result.available && result.remote) { if (result.available && result.remote) {
console.log('[SelfUpdater] Update available: %s → %s', result.local.version, result.remote.version); log.info('updater', 'Update available', { localVersion: result.local.version, remoteVersion: result.remote.version });
await this.applyUpdate(result.remote); await this.applyUpdate(result.remote);
} }
} catch (e) { } catch (e) {
console.error('[SelfUpdater] Auto-update error:', e.message); log.error('updater', e, { phase: 'autoUpdate' });
} }
} }
@@ -606,7 +607,7 @@ class SelfUpdater extends EventEmitter {
fs.mkdirSync(path.dirname(this.notifySecretFile), { recursive: true }); fs.mkdirSync(path.dirname(this.notifySecretFile), { recursive: true });
fs.writeFileSync(this.notifySecretFile, `${secret}\n`, { mode: 0o600 }); fs.writeFileSync(this.notifySecretFile, `${secret}\n`, { mode: 0o600 });
} catch (error) { } catch (error) {
console.warn('[SelfUpdater] Failed to persist notify secret:', error.message); log.warn('updater', 'Failed to persist notify secret', { error: error.message });
} }
return secret; return secret;
} }
@@ -626,7 +627,7 @@ class SelfUpdater extends EventEmitter {
fs.mkdirSync(path.dirname(this.config.instanceIdFile), { recursive: true }); fs.mkdirSync(path.dirname(this.config.instanceIdFile), { recursive: true });
fs.writeFileSync(this.config.instanceIdFile, `${instanceId}\n`, 'utf8'); fs.writeFileSync(this.config.instanceIdFile, `${instanceId}\n`, 'utf8');
} catch (error) { } catch (error) {
console.warn('[SelfUpdater] Failed to persist instance ID:', error.message); log.warn('updater', 'Failed to persist instance ID', { error: error.message });
} }
return instanceId; return instanceId;
} }
@@ -644,7 +645,7 @@ class SelfUpdater extends EventEmitter {
try { try {
fs.writeFileSync(historyPath, JSON.stringify(history, null, 2)); fs.writeFileSync(historyPath, JSON.stringify(history, null, 2));
} catch (e) { } catch (e) {
console.error('[SelfUpdater] Failed to save history:', e.message); log.error('updater', e, { operation: 'saveHistory' });
} }
} }
+17 -16
View File
@@ -8,6 +8,7 @@ const fs = require('fs');
const path = require('path'); const path = require('path');
const lockfile = require('proper-lockfile'); const lockfile = require('proper-lockfile');
const platformPaths = require('../../platform-paths'); const platformPaths = require('../../platform-paths');
const { log } = require('../utils/logging');
const LOCK_DIR = process.env.PORT_LOCK_DIR || path.join(platformPaths.dataDir, '.port-locks'); const LOCK_DIR = process.env.PORT_LOCK_DIR || path.join(platformPaths.dataDir, '.port-locks');
const LOCK_TIMEOUT = 120000; // 2 minutes const LOCK_TIMEOUT = 120000; // 2 minutes
@@ -35,7 +36,7 @@ class PortLockManager {
ensureLockDirectory() { ensureLockDirectory() {
if (!fs.existsSync(LOCK_DIR)) { if (!fs.existsSync(LOCK_DIR)) {
fs.mkdirSync(LOCK_DIR, { recursive: true }); fs.mkdirSync(LOCK_DIR, { recursive: true });
console.log('[PortLockManager] Created lock directory:', LOCK_DIR); log.info('portlock', 'Created lock directory', { dir: LOCK_DIR });
} }
} }
@@ -63,7 +64,7 @@ class PortLockManager {
const releaseFunctions = []; const releaseFunctions = [];
try { try {
console.log(`[PortLockManager] Acquiring locks for ports: ${sortedPorts.join(', ')}`); log.info('portlock', 'Acquiring locks', { ports: sortedPorts });
// Acquire locks in sorted order to prevent deadlocks // Acquire locks in sorted order to prevent deadlocks
for (const port of sortedPorts) { for (const port of sortedPorts) {
@@ -83,7 +84,7 @@ class PortLockManager {
acquiredLocks.push(port); acquiredLocks.push(port);
releaseFunctions.push(release); releaseFunctions.push(release);
console.log(`[PortLockManager] Locked port ${port}`); log.info('portlock', 'Locked port', { port });
} }
// Store lock information // Store lock information
@@ -93,18 +94,18 @@ class PortLockManager {
timestamp: Date.now() timestamp: Date.now()
}); });
console.log(`[PortLockManager] Successfully acquired all locks (ID: ${lockId})`); log.info('portlock', 'Acquired all locks', { lockId });
return lockId; return lockId;
} catch (error) { } catch (error) {
// Release any locks we managed to acquire // Release any locks we managed to acquire
console.error(`[PortLockManager] Failed to acquire all locks:`, error.message); log.error('portlock', error, { operation: 'acquire', lockId });
for (const release of releaseFunctions) { for (const release of releaseFunctions) {
try { try {
await release(); await release();
} catch (releaseError) { } catch (releaseError) {
console.error(`[PortLockManager] Error releasing lock during cleanup:`, releaseError.message); log.error('portlock', releaseError, { operation: 'releaseCleanup', lockId });
} }
} }
@@ -120,11 +121,11 @@ class PortLockManager {
const lockInfo = this.activeLocks.get(lockId); const lockInfo = this.activeLocks.get(lockId);
if (!lockInfo) { if (!lockInfo) {
console.warn(`[PortLockManager] Lock ID ${lockId} not found (may have been released already)`); log.warn('portlock', 'Lock ID not found', { lockId });
return; return;
} }
console.log(`[PortLockManager] Releasing locks for ports: ${lockInfo.ports.join(', ')}`); log.info('portlock', 'Releasing locks', { lockId, ports: lockInfo.ports });
const errors = []; const errors = [];
@@ -133,16 +134,16 @@ class PortLockManager {
await release(); await release();
} catch (error) { } catch (error) {
errors.push(error.message); errors.push(error.message);
console.error(`[PortLockManager] Error releasing lock:`, error.message); log.error('portlock', error, { operation: 'release', lockId });
} }
} }
this.activeLocks.delete(lockId); this.activeLocks.delete(lockId);
if (errors.length > 0) { if (errors.length > 0) {
console.warn(`[PortLockManager] Released locks with ${errors.length} errors`); log.warn('portlock', 'Released locks with errors', { lockId, errorCount: errors.length });
} else { } else {
console.log(`[PortLockManager] Successfully released all locks (ID: ${lockId})`); log.info('portlock', 'Released all locks', { lockId });
} }
} }
@@ -151,7 +152,7 @@ class PortLockManager {
* Removes locks older than LOCK_STALE_THRESHOLD * Removes locks older than LOCK_STALE_THRESHOLD
*/ */
async cleanupStaleLocks() { async cleanupStaleLocks() {
console.log('[PortLockManager] Cleaning up stale locks...'); log.info('portlock', 'Cleaning up stale locks');
this.ensureLockDirectory(); this.ensureLockDirectory();
@@ -174,20 +175,20 @@ class PortLockManager {
// Lock is stale or not locked, safe to remove // Lock is stale or not locked, safe to remove
fs.unlinkSync(lockFilePath); fs.unlinkSync(lockFilePath);
cleaned++; cleaned++;
console.log(`[PortLockManager] Removed stale lock: ${file}`); log.info('portlock', 'Removed stale lock', { file });
} }
} catch (error) { } catch (error) {
// File might not exist or might have been removed by another process // File might not exist or might have been removed by another process
if (error.code !== 'ENOENT') { if (error.code !== 'ENOENT') {
errors++; errors++;
console.warn(`[PortLockManager] Error checking lock ${file}:`, error.message); log.warn('portlock', 'Error checking lock', { file, error: error.message });
} }
} }
} }
console.log(`[PortLockManager] Cleanup complete: ${cleaned} stale locks removed, ${errors} errors`); log.info('portlock', 'Cleanup complete', { cleaned, errors });
} catch (error) { } catch (error) {
console.error('[PortLockManager] Error during cleanup:', error.message); log.error('portlock', error, { operation: 'cleanup' });
} }
} }
+17 -21
View File
@@ -8,6 +8,7 @@ const crypto = require('crypto');
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const platformPaths = require('../../platform-paths'); const platformPaths = require('../../platform-paths');
const { log } = require('../utils/logging');
// Encryption settings // Encryption settings
const ALGORITHM = 'aes-256-gcm'; const ALGORITHM = 'aes-256-gcm';
@@ -65,7 +66,7 @@ function loadOrCreateKey() {
// Check for key in environment variable first // Check for key in environment variable first
if (process.env.DASHCADDY_ENCRYPTION_KEY) { if (process.env.DASHCADDY_ENCRYPTION_KEY) {
encryptionKey = Buffer.from(process.env.DASHCADDY_ENCRYPTION_KEY, 'hex'); encryptionKey = Buffer.from(process.env.DASHCADDY_ENCRYPTION_KEY, 'hex');
console.log('[Crypto] Using encryption key from environment variable'); log.info('crypto', 'Using encryption key from environment variable');
return encryptionKey; return encryptionKey;
} }
@@ -75,16 +76,16 @@ function loadOrCreateKey() {
const keyData = fs.readFileSync(KEY_FILE, 'utf8').trim(); const keyData = fs.readFileSync(KEY_FILE, 'utf8').trim();
if (keyData.length >= 64) { if (keyData.length >= 64) {
encryptionKey = Buffer.from(keyData, 'hex'); encryptionKey = Buffer.from(keyData, 'hex');
console.log('[Crypto] Loaded encryption key from file'); log.info('crypto', 'Loaded encryption key from file');
// First-run bootstrap: if .bak doesn't exist yet, write the current // First-run bootstrap: if .bak doesn't exist yet, write the current
// key to it. This ensures the silent recovery path is available from // key to it. This ensures the silent recovery path is available from
// the very next restart without requiring an explicit rotateKey(). // the very next restart without requiring an explicit rotateKey().
if (!fs.existsSync(KEY_FILE + '.bak')) { if (!fs.existsSync(KEY_FILE + '.bak')) {
try { try {
fs.writeFileSync(KEY_FILE + '.bak', keyData, { mode: 0o600 }); fs.writeFileSync(KEY_FILE + '.bak', keyData, { mode: 0o600 });
console.log(`[Crypto] Seeded ${KEY_FILE}.bak with current key for future fallback`); log.info('crypto', 'Seeded .bak key file for future fallback');
} catch (e) { } catch (e) {
console.warn('[Crypto] Could not seed .bak key file:', e.message); log.warn('crypto', 'Could not seed .bak key file', { error: e.message });
} }
} }
// Try fallback to .bak key if primary can't decrypt existing credentials. // Try fallback to .bak key if primary can't decrypt existing credentials.
@@ -98,14 +99,14 @@ function loadOrCreateKey() {
encryptionKey = tryFallbackToBackupKey(Buffer.from(keyData, 'hex'), Buffer.from(backupData, 'hex')); encryptionKey = tryFallbackToBackupKey(Buffer.from(keyData, 'hex'), Buffer.from(backupData, 'hex'));
} }
} catch (e) { } catch (e) {
console.warn('[Crypto] Could not check backup key:', e.message); log.warn('crypto', 'Could not check backup key', { error: e.message });
} }
} }
return encryptionKey; return encryptionKey;
} }
// File exists but key is invalid/empty - will generate new one below // File exists but key is invalid/empty - will generate new one below
} catch (error) { } catch (error) {
console.error('[Crypto] Error loading key file:', error.message); log.error('crypto', error, { operation: 'loadKey' });
} }
} }
@@ -115,10 +116,10 @@ function loadOrCreateKey() {
try { try {
// Save key to file with restricted permissions // Save key to file with restricted permissions
fs.writeFileSync(KEY_FILE, encryptionKey.toString('hex'), { mode: 0o600 }); fs.writeFileSync(KEY_FILE, encryptionKey.toString('hex'), { mode: 0o600 });
console.log('[Crypto] Generated and saved new encryption key'); log.info('crypto', 'Generated and saved new encryption key');
} catch (error) { } catch (error) {
console.warn('[Crypto] Could not save key to file:', error.message); log.warn('crypto', 'Could not save key to file', { error: error.message });
console.warn('[Crypto] Key will be regenerated on restart - credentials will need to be re-entered'); log.warn('crypto', 'Key will be regenerated on restart - credentials will need to be re-entered');
} }
return encryptionKey; return encryptionKey;
@@ -171,12 +172,7 @@ function tryFallbackToBackupKey(primaryKey, backupKey) {
if (tryDecrypt(primaryKey)) return primaryKey; if (tryDecrypt(primaryKey)) return primaryKey;
if (tryDecrypt(backupKey)) { if (tryDecrypt(backupKey)) {
console.warn( log.warn('crypto', 'Primary encryption key failed to decrypt credentials; fell back to .encryption-key.bak. Consider rotating the key explicitly via the credential-manager API.');
'[Crypto] Primary encryption key failed to decrypt credentials; ' +
'fell back to .encryption-key.bak. The current primary key was set ' +
'without preserving the original. Consider rotating the key explicitly ' +
'via the credential-manager API to avoid this warning next restart.'
);
return backupKey; return backupKey;
} }
return primaryKey; // neither works — credential-manager.diagnose() will report 'unreadable' return primaryKey; // neither works — credential-manager.diagnose() will report 'unreadable'
@@ -291,7 +287,7 @@ function decryptFields(obj, fields = null) {
try { try {
result[field] = decrypt(result[field]); result[field] = decrypt(result[field]);
} catch (error) { } catch (error) {
console.error(`[Crypto] Failed to decrypt field '${field}':`, error.message); log.error('crypto', error, { field, operation: 'decryptField' });
// Leave the field as-is if decryption fails // Leave the field as-is if decryption fails
} }
} }
@@ -315,7 +311,7 @@ function migrateToEncrypted(credentials, sensitiveFields) {
return credentials; // Already encrypted return credentials; // Already encrypted
} }
console.log('[Crypto] Migrating plaintext credentials to encrypted format'); log.info('crypto', 'Migrating plaintext credentials to encrypted format');
return encryptFields(credentials, sensitiveFields); return encryptFields(credentials, sensitiveFields);
} }
@@ -340,10 +336,10 @@ function readEncryptedFile(filePath, sensitiveFields = ['password', 'token', 'ap
} }
// Plain text data - migrate it // Plain text data - migrate it
console.log(`[Crypto] Found plaintext data in ${filePath}, will encrypt on next save`); log.info('crypto', 'Found plaintext data', { filePath });
return parsed; return parsed;
} catch (error) { } catch (error) {
console.error(`[Crypto] Error reading ${filePath}:`, error.message); log.error('crypto', error, { filePath, operation: 'readFile' });
return null; return null;
} }
} }
@@ -357,7 +353,7 @@ function readEncryptedFile(filePath, sensitiveFields = ['password', 'token', 'ap
function writeEncryptedFile(filePath, credentials, sensitiveFields = ['password', 'token', 'apiKey', 'secret']) { function writeEncryptedFile(filePath, credentials, sensitiveFields = ['password', 'token', 'apiKey', 'secret']) {
const encrypted = encryptFields(credentials, sensitiveFields); const encrypted = encryptFields(credentials, sensitiveFields);
fs.writeFileSync(filePath, JSON.stringify(encrypted, null, 2), 'utf8'); fs.writeFileSync(filePath, JSON.stringify(encrypted, null, 2), 'utf8');
console.log(`[Crypto] Saved encrypted credentials to ${filePath}`); log.info('crypto', 'Saved encrypted credentials', { filePath });
} }
/** /**
@@ -377,7 +373,7 @@ function rotateKey() {
try { try {
fs.writeFileSync(KEY_FILE + '.bak', oldKey.toString('hex'), { mode: 0o600 }); fs.writeFileSync(KEY_FILE + '.bak', oldKey.toString('hex'), { mode: 0o600 });
} catch (error) { } catch (error) {
console.warn(`[Crypto] Could not save backup key to ${KEY_FILE}.bak:`, error.message); log.warn('crypto', 'Could not save backup key', { error: error.message });
} }
try { try {
+16 -15
View File
@@ -9,6 +9,7 @@ const path = require('path');
const https = require('https'); const https = require('https');
const Docker = require('dockerode'); const Docker = require('dockerode');
const platformPaths = require('../../platform-paths'); const platformPaths = require('../../platform-paths');
const { log } = require('../utils/logging');
const docker = new Docker(); const docker = new Docker();
@@ -19,7 +20,7 @@ class DockerSecurity {
constructor() { constructor() {
this.config = this.loadConfig(); this.config = this.loadConfig();
this.mode = VERIFICATION_MODE; this.mode = VERIFICATION_MODE;
console.log(`[DockerSecurity] Initialized in ${this.mode} mode`); log.info('security', 'Docker security initialized', { mode: this.mode });
} }
/** /**
@@ -32,7 +33,7 @@ class DockerSecurity {
return JSON.parse(data); return JSON.parse(data);
} }
} catch (error) { } catch (error) {
console.warn(`[DockerSecurity] Failed to load config: ${error.message}`); log.warn('security', 'Failed to load config', { error: error.message });
} }
// Default configuration // Default configuration
@@ -51,7 +52,7 @@ class DockerSecurity {
try { try {
fs.writeFileSync(SECURITY_CONFIG_FILE, JSON.stringify(this.config, null, 2)); fs.writeFileSync(SECURITY_CONFIG_FILE, JSON.stringify(this.config, null, 2));
} catch (error) { } catch (error) {
console.error(`[DockerSecurity] Failed to save config: ${error.message}`); log.error('security', error, { operation: 'saveConfig' });
} }
} }
@@ -110,7 +111,7 @@ class DockerSecurity {
repository = repository.split(':')[0]; repository = repository.split(':')[0];
} }
console.log(`[DockerSecurity] Fetching manifest for ${registry}/${repository}:${tag}`); log.info('security', 'Fetching manifest', { registry, repository, tag });
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const isDockerHub = registry === 'registry-1.docker.io'; const isDockerHub = registry === 'registry-1.docker.io';
@@ -216,7 +217,7 @@ class DockerSecurity {
if (this.config.updateTrustedOnPull) { if (this.config.updateTrustedOnPull) {
this.config.trustedDigests[imageName] = actualDigest; this.config.trustedDigests[imageName] = actualDigest;
this.saveConfig(); this.saveConfig();
console.log(`[DockerSecurity] Added trusted digest for ${imageName}`); log.info('security', 'Added trusted digest', { imageName });
} }
} }
} else if (actualDigest === trustedDigest) { } else if (actualDigest === trustedDigest) {
@@ -250,26 +251,26 @@ class DockerSecurity {
* @returns {Promise<object>} Verification result * @returns {Promise<object>} Verification result
*/ */
async verifyPulledImage(imageName) { async verifyPulledImage(imageName) {
console.log(`[DockerSecurity] Verifying image: ${imageName}`); log.info('security', 'Verifying image', { imageName });
try { try {
const actualDigest = await this.getImageDigest(imageName); const actualDigest = await this.getImageDigest(imageName);
const result = await this.verifyImageDigest(imageName, actualDigest); const result = await this.verifyImageDigest(imageName, actualDigest);
if (result.action === 'reject') { if (result.action === 'reject') {
console.error(`[DockerSecurity] REJECTED: ${result.reason}`); log.error('security', 'Image REJECTED', { imageName, reason: result.reason });
throw new Error(`Image verification failed: ${result.reason}`); throw new Error(`Image verification failed: ${result.reason}`);
} else if (result.action === 'warn') { } else if (result.action === 'warn') {
console.warn(`[DockerSecurity] WARNING: ${result.reason}`); log.warn('security', 'Image WARNING', { imageName, reason: result.reason });
console.warn(`[DockerSecurity] Expected: ${result.trustedDigest}`); log.warn('security', 'Expected digest', { imageName, digest: result.trustedDigest });
console.warn(`[DockerSecurity] Actual: ${result.actualDigest}`); log.warn('security', 'Actual digest', { imageName, digest: result.actualDigest });
} else { } else {
console.log(`[DockerSecurity] ACCEPTED: ${result.reason}`); log.info('security', 'Image ACCEPTED', { imageName, reason: result.reason });
} }
return result; return result;
} catch (error) { } catch (error) {
console.error(`[DockerSecurity] Verification error: ${error.message}`); log.error('security', error, { imageName, operation: 'verify' });
if (this.mode === 'strict') { if (this.mode === 'strict') {
throw error; throw error;
@@ -294,7 +295,7 @@ class DockerSecurity {
setTrustedDigest(imageName, digest) { setTrustedDigest(imageName, digest) {
this.config.trustedDigests[imageName] = digest; this.config.trustedDigests[imageName] = digest;
this.saveConfig(); this.saveConfig();
console.log(`[DockerSecurity] Updated trusted digest for ${imageName}`); log.info('security', 'Updated trusted digest', { imageName });
} }
/** /**
@@ -304,7 +305,7 @@ class DockerSecurity {
removeTrustedDigest(imageName) { removeTrustedDigest(imageName) {
delete this.config.trustedDigests[imageName]; delete this.config.trustedDigests[imageName];
this.saveConfig(); this.saveConfig();
console.log(`[DockerSecurity] Removed trusted digest for ${imageName}`); log.info('security', 'Removed trusted digest', { imageName });
} }
/** /**
@@ -325,7 +326,7 @@ class DockerSecurity {
this.mode = mode; this.mode = mode;
this.config.verificationMode = mode; this.config.verificationMode = mode;
this.saveConfig(); this.saveConfig();
console.log(`[DockerSecurity] Verification mode set to: ${mode}`); log.info('security', 'Verification mode set', { mode });
} }
/** /**
+6 -5
View File
@@ -37,6 +37,7 @@
*/ */
const fs = require('fs'); const fs = require('fs');
const { log } = require('../utils/logging');
const path = require('path'); const path = require('path');
const os = require('os'); const os = require('os');
const platformPaths = require('../../platform-paths'); const platformPaths = require('../../platform-paths');
@@ -95,7 +96,7 @@ function createTail({ filePath, stateFile, onLine, label = 'tail', pollMs = 1000
for (const line of lines) { for (const line of lines) {
if (line.trim()) { if (line.trim()) {
try { onLine(line); } catch (e) { try { onLine(line); } catch (e) {
console.error(`[${label}] onLine threw:`, e.message); log.error('events', e, { worker: label, phase: 'onLine' });
} }
} }
} }
@@ -106,7 +107,7 @@ function createTail({ filePath, stateFile, onLine, label = 'tail', pollMs = 1000
setTimeout(tick, pollMs); setTimeout(tick, pollMs);
}); });
stream.on('error', (e) => { stream.on('error', (e) => {
console.error(`[${label}] read error:`, e.message); log.error('events', e, { worker: label, phase: 'read' });
setTimeout(tick, pollMs * 5); setTimeout(tick, pollMs * 5);
}); });
}); });
@@ -267,11 +268,11 @@ function startFail2banWorker({ log } = {}) {
function startAll({ log } = {}) { function startAll({ log } = {}) {
const workers = []; const workers = [];
try { workers.push(startCaddyWorker({ log })); } try { workers.push(startCaddyWorker({ log })); }
catch (e) { console.error('[workers] caddy worker failed to start:', e.message); } catch (e) { log.error('events', e, { worker: 'caddy', phase: 'start' }); }
try { workers.push(startSharedBansWorker({ log })); } try { workers.push(startSharedBansWorker({ log })); }
catch (e) { console.error('[workers] shared_bans worker failed to start:', e.message); } catch (e) { log.error('events', e, { worker: 'shared_bans', phase: 'start' }); }
try { workers.push(startFail2banWorker({ log })); } try { workers.push(startFail2banWorker({ log })); }
catch (e) { console.error('[workers] fail2ban worker failed to start:', e.message); } catch (e) { log.error('events', e, { worker: 'fail2ban', phase: 'start' }); }
return { return {
stop() { workers.forEach(w => { try { w.stop(); } catch {} }); }, stop() { workers.forEach(w => { try { w.stop(); } catch {} }); },
workers, workers,
@@ -7,6 +7,7 @@
const { execSync, execFileSync } = require('child_process'); const { execSync, execFileSync } = require('child_process');
const os = require('os'); const os = require('os');
const crypto = require('crypto'); const crypto = require('crypto');
const { log } = require('../utils/logging');
const SERVICE_NAME = 'DashCaddy'; const SERVICE_NAME = 'DashCaddy';
const ACCOUNT_PREFIX = 'dashcaddy'; const ACCOUNT_PREFIX = 'dashcaddy';
@@ -44,7 +45,7 @@ class KeychainManager {
} }
return false; return false;
} catch { } catch {
console.warn('[Keychain] OS keychain not available, will use encrypted file storage'); log.warn('keychain', 'OS keychain not available, will use encrypted file storage');
return false; return false;
} }
} }
@@ -72,7 +73,7 @@ class KeychainManager {
} }
return false; return false;
} catch (error) { } catch (error) {
console.error(`[Keychain] Failed to store ${key}:`, error.message); log.error('keychain', error, { key, operation: 'store' });
return false; return false;
} }
} }
@@ -99,7 +100,7 @@ class KeychainManager {
} }
return null; return null;
} catch (error) { } catch (error) {
console.error(`[Keychain] Failed to retrieve ${key}:`, error.message); log.error('keychain', error, { key, operation: 'retrieve' });
return null; return null;
} }
} }
@@ -126,7 +127,7 @@ class KeychainManager {
} }
return false; return false;
} catch (error) { } catch (error) {
console.error(`[Keychain] Failed to delete ${key}:`, error.message); log.error('keychain', error, { key, operation: 'delete' });
return false; return false;
} }
} }