From 689fe861f130067f0ddb69d4371d06cf14b3008e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=9B=B7=E7=94=B5=E8=8A=BD=E8=A1=A3?= Date: Sat, 23 May 2026 22:35:35 -0400 Subject: [PATCH] Make audit events immutable --- .../033-audit-event-immutability.ts | 16 ++++++++++++++ AgentCompany-New/src/main/database/schema.ts | 2 ++ .../tests/unit/audit-service.test.ts | 22 +++++++++++++++++++ .../tests/unit/domain-services.test.ts | 2 +- 4 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 AgentCompany-New/src/main/database/migrations/033-audit-event-immutability.ts diff --git a/AgentCompany-New/src/main/database/migrations/033-audit-event-immutability.ts b/AgentCompany-New/src/main/database/migrations/033-audit-event-immutability.ts new file mode 100644 index 00000000..42bccb6b --- /dev/null +++ b/AgentCompany-New/src/main/database/migrations/033-audit-event-immutability.ts @@ -0,0 +1,16 @@ +export const auditEventImmutabilitySchema = ` + create trigger if not exists trg_audit_events_no_update + before update on audit_events + begin + select raise(abort, 'Audit events are immutable.'); + end; + + create trigger if not exists trg_audit_events_no_delete + before delete on audit_events + begin + select raise(abort, 'Audit events are immutable.'); + end; + + insert into schema_migrations(version, name, applied_at) + values (33, 'audit_event_immutability', datetime('now')); +`; diff --git a/AgentCompany-New/src/main/database/schema.ts b/AgentCompany-New/src/main/database/schema.ts index 368cf87b..3c6dbcbf 100644 --- a/AgentCompany-New/src/main/database/schema.ts +++ b/AgentCompany-New/src/main/database/schema.ts @@ -31,6 +31,7 @@ import { fileHandoffRecordsSchema } from "./migrations/029-file-handoff-records" import { approvalSourceRefsSchema } from "./migrations/030-approval-source-refs"; import { providerRequestWorkspaceSchema } from "./migrations/031-provider-request-workspace"; import { browserActionMetadataSchema } from "./migrations/032-browser-action-metadata"; +import { auditEventImmutabilitySchema } from "./migrations/033-audit-event-immutability"; interface Migration { version: number; @@ -71,6 +72,7 @@ const MIGRATIONS: Migration[] = [ { version: 30, name: "approval_source_refs", sql: approvalSourceRefsSchema }, { version: 31, name: "provider_request_workspace", sql: providerRequestWorkspaceSchema }, { version: 32, name: "browser_action_metadata", sql: browserActionMetadataSchema }, + { version: 33, name: "audit_event_immutability", sql: auditEventImmutabilitySchema }, ]; const SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1].version; diff --git a/AgentCompany-New/tests/unit/audit-service.test.ts b/AgentCompany-New/tests/unit/audit-service.test.ts index ea4aaa7d..3c18fc00 100644 --- a/AgentCompany-New/tests/unit/audit-service.test.ts +++ b/AgentCompany-New/tests/unit/audit-service.test.ts @@ -13,6 +13,28 @@ function createConnection(): DatabaseConnection { } describe("audit service", () => { + test("keeps core audit events immutable", () => { + const connection = createConnection(); + const organization = new OrganizationService(connection.db); + let auditId = ""; + + connection.transaction(() => { + const orgId = organization.createOrganization({ + organizationName: "Acme Operations", + employeeName: "Dana Lee", + mission: "Coordinate agents with auditable approvals.", + goal: "Ship a verified control plane.", + }); + auditId = (connection.db.prepare("select id from audit_events where org_id = ? limit 1").get(orgId) as { id: string }).id; + }); + + expect(() => connection.db.prepare("update audit_events set action = ? where id = ?") + .run("changed", auditId)).toThrow("Audit events are immutable."); + expect(() => connection.db.prepare("delete from audit_events where id = ?") + .run(auditId)).toThrow("Audit events are immutable."); + connection.close(); + }); + test("creates thread scoped replay runs from immutable audit events", () => { const connection = createConnection(); const organization = new OrganizationService(connection.db); diff --git a/AgentCompany-New/tests/unit/domain-services.test.ts b/AgentCompany-New/tests/unit/domain-services.test.ts index 585355e4..12c92893 100644 --- a/AgentCompany-New/tests/unit/domain-services.test.ts +++ b/AgentCompany-New/tests/unit/domain-services.test.ts @@ -23,7 +23,7 @@ describe("domain services", () => { const connection = createConnection(); const rows = connection.db.prepare("select version from schema_migrations order by version asc").all() as Array<{ version: number }>; - expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]); + expect(rows.map((row) => row.version)).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33]); connection.close(); });