| 1 | import { describe, expect, it } from "vitest"; |
| 2 | import { AUDIT_RETENTION_DAYS, pruneAuditLog } from "../../src/lib/directory.js"; |
| 3 | import { testD1 } from "./stubs/d1.js"; |
| 4 | |
| 5 | // The privacy policy says the audit log is kept 2 years: entries older than that are deleted every hour. |
| 6 | describe("audit log retention", () => { |
| 7 | it("deletes entries older than two years and keeps the rest", async () => { |
| 8 | const DB = testD1(); |
| 9 | const at = new Date("2026-10-14T03:00:00Z"); |
| 10 | const daysAgo = (d: number) => new Date(at.getTime() - d * 86400_000).toISOString(); |
| 11 | const add = DB.sqlite.prepare("INSERT INTO audit_log (id, at, action) VALUES (?, ?, 'session.create')"); |
| 12 | add.run("old1", daysAgo(AUDIT_RETENTION_DAYS + 1)); |
| 13 | add.run("old2", daysAgo(AUDIT_RETENTION_DAYS + 400)); |
| 14 | add.run("kept1", daysAgo(AUDIT_RETENTION_DAYS - 1)); |
| 15 | add.run("kept2", daysAgo(0)); |
| 16 | expect(AUDIT_RETENTION_DAYS).toBe(730); |
| 17 | expect(await pruneAuditLog(DB, at)).toBe(2); |
| 18 | const ids = (DB.sqlite.prepare("SELECT id FROM audit_log ORDER BY id").all() as Array<{ id: string }>).map((r) => r.id); |
| 19 | expect(ids).toEqual(["kept1", "kept2"]); |
| 20 | }); |
| 21 | |
| 22 | it("deletes a bounded batch at a time", async () => { |
| 23 | const DB = testD1(); |
| 24 | const at = new Date("2026-10-14T03:00:00Z"); |
| 25 | const add = DB.sqlite.prepare("INSERT INTO audit_log (id, at, action) VALUES (?, ?, 'git.push')"); |
| 26 | for (let i = 0; i < 5; i++) add.run(`old${i}`, "2020-01-01T00:00:00.000Z"); |
| 27 | expect(await pruneAuditLog(DB, at, 3)).toBe(3); |
| 28 | expect(await pruneAuditLog(DB, at, 3)).toBe(2); |
| 29 | expect(await pruneAuditLog(DB, at, 3)).toBe(0); |
| 30 | }); |
| 31 | }); |