feat(audit): attribute workflow audits to their run and merge a run's repeated row audits
Merged
WA
3d ago+528+528+012345678901234567890123456789-28-28-01234567890123456789
Summary
- Executor-delegated audit actors now carry
workflowIdandexecutionId, so a workflow-made audit entry traces back to its workflow and run (before, only a per-calldelegationIdwas recorded) - New
recordAuditRollup/flushAuditRollupsin@sim/audit: repeats of the same event within a 2s window (max 100 per row) become one row. Nothing is dropped:- a lone occurrence is written exactly as it is today
- a merged row sums the counters, collects every identifier (
rowIds,delegationIds), and recordsrollup: { entries, firstAt, lastAt }
- Table row audits (
table.updatedfrom insert/update/delete/upsert/replace) opt in, but only for an executor delegation that names its run and has no client request. They merge only within the same execution, table, op, and metadata; session, API key, CLI, and copilot writes are unchanged - Server-side
credential.accessed(no client request, e.g. a run refreshing a token per tool call) merges per actor + credential; requests with a client still write one row each - No-loss guarantees:
executeWorkflowCoreawaitsflushAuditRollups()before returning, so a background run's process can't freeze or exit with rows pending; the flush also waits for writes already in flight- window timers are ref'd, so a natural process exit still writes them
- each pending row is its own insert, so one bad row can't take others with it
created_atstays the DB default, so drains' 5-minute stability cursor can't skip a delayed row- the surface is captured when the event is recorded, not when it's flushed
- Docs: audit-logs page describes merged entries and the new actor fields
Type of Change
- New feature
Testing
row-audit.integration.ts(real Postgres): 3 new cases- one run's repeated inserts → 1 row with all row ids, summed count, distinct delegation ids
- two runs never merge
- a lone run write keeps today's exact shape
- all 3 fail with the rollup branch disabled and pass with it; the 8 existing cases still pass
- Unit:
principal.test.ts,token-resolution.test.ts(negative cases now also assert no rollup),authorized-workspace-use-case.test.ts,execution-core.test.ts,rows.test.ts, selectors (427 tests) bun run lint; type-check andcheck:auditsleft to CI
Checklist
- Code follows project style guidelines
- Self-reviewed my changes
- Tests added/updated and passing (new tests pass the
test-auditauthoring gate) - No new warnings introduced
- I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)