fix: harden upload cancellation and audit logging

Preserve pre-start and batch cancellation requests, reject late upload success after cancellation, and wait for cancellation acknowledgements before removing queue entries.

Separate formatted link logs from privacy-safe source cleanup and upload plan audits, persist audit fallback paths, redact support bundles, and expose audit diagnostics safely.

Improve queue selection and destructive-action clarity, show the Settings save action only while changes are pending, and add regression coverage for all updated behavior.
This commit is contained in:
Sucukdeluxe
2026-08-13 14:31:46 +02:00
parent 59cead80c6
commit bfb3a39fed
20 changed files with 733 additions and 101 deletions
+15 -9
View File
@@ -14,6 +14,14 @@
const fs = require('fs');
const path = require('path');
function getRotatedLogPath(filePath, backup) {
const index = Number(backup);
if (!Number.isInteger(index) || index < 1) return filePath;
const ext = path.extname(filePath);
const base = filePath.slice(0, filePath.length - ext.length);
return `${base}.${index}${ext}`;
}
function maybeRotateLogFile(filePath, maxBytes, maxBackups = 3, log = () => {}) {
if (!filePath || !Number.isFinite(maxBytes) || maxBytes <= 0) return false;
let size = 0;
@@ -29,24 +37,22 @@ function maybeRotateLogFile(filePath, maxBytes, maxBackups = 3, log = () => {})
}
if (size <= maxBytes) return false;
const ext = path.extname(filePath);
const base = filePath.slice(0, filePath.length - ext.length);
// Drop the oldest backup if it exists, then shift each numbered backup up
// one slot. Errors are ignored: missing intermediate backups are normal,
// failed renames just mean we'll rotate again next time.
try { fs.unlinkSync(`${base}.${maxBackups}${ext}`); } catch {}
try { fs.unlinkSync(getRotatedLogPath(filePath, maxBackups)); } catch {}
for (let i = maxBackups - 1; i >= 1; i--) {
try { fs.renameSync(`${base}.${i}${ext}`, `${base}.${i + 1}${ext}`); } catch {}
try { fs.renameSync(getRotatedLogPath(filePath, i), getRotatedLogPath(filePath, i + 1)); } catch {}
}
try {
fs.renameSync(filePath, `${base}.1${ext}`);
log(`logRotation: rotated ${filePath} (${(size / 1024 / 1024).toFixed(1)} MB) → ${base}.1${ext}`);
const backupPath = getRotatedLogPath(filePath, 1);
fs.renameSync(filePath, backupPath);
log(`logRotation: rotated ${filePath} (${(size / 1024 / 1024).toFixed(1)} MB) → ${backupPath}`);
return true;
} catch (err) {
log(`logRotation: rename ${filePath}${base}.1${ext} failed: ${err.message}`);
log(`logRotation: rename ${filePath}${getRotatedLogPath(filePath, 1)} failed: ${err.message}`);
return false;
}
}
module.exports = { maybeRotateLogFile };
module.exports = { getRotatedLogPath, maybeRotateLogFile };