fix(cleanup): prune mcp_tool_audit/a2a_task_events by created_at column (#9963)

Both tables (002_mcp_a2a_tables.sql) store their row timestamp in
created_at; the cleanup queries used WHERE timestamp < ? which does not
exist, so every boot-time cleanup logged:
  Error cleaning mcp_tool_audit: SqliteError: no such column: timestamp
  Error cleaning a2a_task_events: SqliteError: no such column: timestamp
and retention pruning for these two tables never ran. Fix the DELETE
columns and align the log labels/doc comments with the real table names.

Adds source-level invariant tests (cleanup-column-fix.test.mjs) asserting
the created_at column for both tables.
This commit is contained in:
Donald Thompson
2026-08-09 20:28:02 -07:00
committed by GitHub
parent 9cd5d64484
commit f390327c88
2 changed files with 34 additions and 8 deletions

View File

@@ -164,7 +164,7 @@ export async function cleanupCompressionAnalytics(): Promise<CleanupResult> {
}
/**
* Clean up old mcp_audit_log based on retention settings.
* Clean up old mcp_tool_audit based on retention settings.
*/
export async function cleanupMcpAudit(): Promise<CleanupResult> {
const db = getDbInstance();
@@ -178,15 +178,15 @@ export async function cleanupMcpAudit(): Promise<CleanupResult> {
const result: CleanupResult = { deleted: 0, errors: 0 };
try {
const stmt = db.prepare("DELETE FROM mcp_tool_audit WHERE timestamp < ?");
const stmt = db.prepare("DELETE FROM mcp_tool_audit WHERE created_at < ?");
const runResult = stmt.run(cutoffISO);
result.deleted = runResult.changes;
console.log(
`[Cleanup] Deleted ${result.deleted} mcp_audit_log older than ${retentionDays} days`
`[Cleanup] Deleted ${result.deleted} mcp_tool_audit older than ${retentionDays} days`
);
} catch (err: unknown) {
console.error("[Cleanup] Error cleaning mcp_audit_log:", err);
console.error("[Cleanup] Error cleaning mcp_tool_audit:", err);
result.errors++;
}
@@ -194,7 +194,7 @@ export async function cleanupMcpAudit(): Promise<CleanupResult> {
}
/**
* Clean up old a2a_events based on retention settings.
* Clean up old a2a_task_events based on retention settings.
*/
export async function cleanupA2aEvents(): Promise<CleanupResult> {
const db = getDbInstance();
@@ -208,13 +208,13 @@ export async function cleanupA2aEvents(): Promise<CleanupResult> {
const result: CleanupResult = { deleted: 0, errors: 0 };
try {
const stmt = db.prepare("DELETE FROM a2a_task_events WHERE timestamp < ?");
const stmt = db.prepare("DELETE FROM a2a_task_events WHERE created_at < ?");
const runResult = stmt.run(cutoffISO);
result.deleted = runResult.changes;
console.log(`[Cleanup] Deleted ${result.deleted} a2a_events older than ${retentionDays} days`);
console.log(`[Cleanup] Deleted ${result.deleted} a2a_task_events older than ${retentionDays} days`);
} catch (err: unknown) {
console.error("[Cleanup] Error cleaning a2a_events:", err);
console.error("[Cleanup] Error cleaning a2a_task_events:", err);
result.errors++;
}

View File

@@ -112,3 +112,29 @@ test("cleanup: memories uses correct table name (not 'memory_entries')", () => {
"must NOT use non-existent table name memory_entries"
);
});
test("cleanup: mcp_tool_audit prunes by created_at (existing column), not timestamp", () => {
// mcp_tool_audit has created_at (see 002_mcp_a2a_tables.sql); timestamp does
// not exist, so WHERE timestamp < ? raised SqliteError "no such column" at
// every boot-time cleanup and the retention pruning never ran.
assert.ok(
source.includes("DELETE FROM mcp_tool_audit WHERE created_at < ?"),
"mcp_tool_audit cleanup must use created_at column"
);
assert.ok(
!source.includes("DELETE FROM mcp_tool_audit WHERE timestamp"),
"must NOT use timestamp for mcp_tool_audit (column doesn't exist)"
);
});
test("cleanup: a2a_task_events prunes by created_at (existing column), not timestamp", () => {
// Same schema fact for a2a_task_events (created_at, no timestamp column).
assert.ok(
source.includes("DELETE FROM a2a_task_events WHERE created_at < ?"),
"a2a_task_events cleanup must use created_at column"
);
assert.ok(
!source.includes("DELETE FROM a2a_task_events WHERE timestamp"),
"must NOT use timestamp for a2a_task_events (column doesn't exist)"
);
});