fix(audit): require integer rolling retention keep limits

Validate keepPerFamily/--keep-per-family as non-negative integers, remove silent flooring, add regression coverage, and sync runbook/docs wording.
This commit is contained in:
William Valentin
2026-02-27 13:11:31 -08:00
parent c68fd2498e
commit 06998ac65d
9 changed files with 46 additions and 12 deletions
@@ -98,6 +98,10 @@ describe('phase0BaselineArtifactRetention', () => {
expect(() => planRollingPhase0ArtifactRetention([], -1)).toThrow('keepPerFamily');
});
it('rejects non-integer keep limit', () => {
expect(() => planRollingPhase0ArtifactRetention([], 1.5)).toThrow('keepPerFamily');
});
it('ignores malformed rolling tags with impossible date or time values', () => {
const rows = collectRollingPhase0ArtifactFiles([
'phase0_baseline_live_2026-13-27-010203.json',
+8 -2
View File
@@ -142,11 +142,17 @@ export function planRollingPhase0ArtifactRetention(
fileNames: string[],
keepPerFamily: number,
): Phase0RollingArtifactRetentionPlan {
if (!Number.isFinite(keepPerFamily) || keepPerFamily < 0) {
if (!Number.isFinite(keepPerFamily)) {
throw new Error('keepPerFamily must be a finite integer greater than or equal to 0.');
}
if (!Number.isInteger(keepPerFamily)) {
throw new Error('keepPerFamily must be an integer greater than or equal to 0.');
}
if (keepPerFamily < 0) {
throw new Error('keepPerFamily must be greater than or equal to 0.');
}
const keepLimit = Math.floor(keepPerFamily);
const keepLimit = keepPerFamily;
const parsed = collectRollingPhase0ArtifactFiles(fileNames);
const keep: Phase0RollingArtifactFile[] = [];