fix(audit): validate phase0 artifact tag inputs

Add shared artifact-tag normalization/validation and apply it to capture, drift, and prune scripts for --tag/--report-tag/--baseline-tag paths. Architecture diagrams reviewed; no flow changes required.
This commit is contained in:
William Valentin
2026-02-27 13:25:35 -08:00
parent 98f954de0d
commit 5b9bcbafee
9 changed files with 66 additions and 8 deletions
+2 -1
View File
@@ -4,6 +4,7 @@ import { mkdir, writeFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { parseArgs } from 'node:util';
import { queryAuditLogs } from '../src/audit/export.js';
import { normalizeArtifactTag } from '../src/audit/artifactTag.js';
import {
capturePhase0LiveBaselineEvents,
type Phase0BackendTarget,
@@ -196,7 +197,7 @@ async function main(): Promise<void> {
}
const auditPath = expandHomePath(values.audit ?? '~/.local/share/flynn/audit.log');
const tag = values.tag ?? isoDateTagNow();
const tag = normalizeArtifactTag(values.tag ?? isoDateTagNow(), '--tag');
const channels = parseCsv(values.channel);
let sources = parseSources(values.source);
const backendTargets = parseBackendTargets(values.backend);
@@ -3,6 +3,7 @@
import { mkdir, readdir, readFile, writeFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { parseArgs } from 'node:util';
import { normalizeArtifactTag } from '../src/audit/artifactTag.js';
import {
comparePhase0BaselineDrift,
evaluatePhase0BaselineDriftGate,
@@ -366,10 +367,14 @@ async function main(): Promise<void> {
const artifactsDir = resolve(values['artifacts-dir'] ?? 'docs/plans/artifacts');
const backends = parseBackends(values.backend);
const candidateTag = values.tag;
const baselineTag = values['baseline-tag'];
const candidateTag = values.tag
? normalizeArtifactTag(values.tag, '--tag')
: undefined;
const baselineTag = values['baseline-tag']
? normalizeArtifactTag(values['baseline-tag'], '--baseline-tag')
: undefined;
const format = parseFormat(values.format);
const reportTag = values['report-tag'] ?? isoDateTagNow();
const reportTag = normalizeArtifactTag(values['report-tag'] ?? isoDateTagNow(), '--report-tag');
const writeDefaultArtifacts = Boolean(values['write-default-artifacts']);
const maxAgeHours = parseOptionalNumber(values['max-age-hours'], '--max-age-hours');
if (typeof maxAgeHours === 'number' && maxAgeHours < 0) {
+2 -1
View File
@@ -3,6 +3,7 @@
import { mkdir, readdir, rm, writeFile } from 'node:fs/promises';
import { dirname, resolve } from 'node:path';
import { parseArgs } from 'node:util';
import { normalizeArtifactTag } from '../src/audit/artifactTag.js';
import {
planRollingPhase0ArtifactRetention,
type Phase0RollingArtifactRetentionPlan,
@@ -103,7 +104,7 @@ async function main(): Promise<void> {
const keepPerFamily = parseOptionalInteger(values['keep-per-family'], '--keep-per-family') ?? 8;
const apply = Boolean(values.apply);
const format = values.format ?? 'text';
const reportTag = values['report-tag'] ?? isoDateTagNow();
const reportTag = normalizeArtifactTag(values['report-tag'] ?? isoDateTagNow(), '--report-tag');
const writeDefaultArtifacts = Boolean(values['write-default-artifacts']);
if (format !== 'text' && format !== 'json') {