Repository navigation
feat(admin): export audit trail as CSV and strictly validate enterprise list queries - #751
Merged
Merged
Conversation
Ayush7614
requested review from
MikeRyanDev,
davidmckayv,
guidovizoso,
mxmzb and
tylerslaton
as code owners
October 7, 2026 07:14
…pped at the cap Audit rows carry text people and Bots control, and a CSV cell starting with =, +, - or @ runs as a formula in a spreadsheet, so such a cell is prefixed with a quote and opens as text. Taking the trail out is now on the trail itself, as audit.exported with who, how many rows and which filter. An export that hit the 5,000-row cap set a header the page ignored, so the file read as the whole trail; the header now carries the row count and the page says the file holds the newest that many.
1123786563
pushed a commit
to 1123786563/OpenBot
that referenced
this pull request
Oct 13, 2026
合入上游 14 个提交(CopilotKit#758-CopilotKit#778):sidebar Bots/Skills 重构、Bot 页面树 (bots.$agentId.*)、legacy 路由重定向、GitHub/Slack 账号链接(CopilotKit#763)、 memory-on-Intelligence 与默认开启(CopilotKit#773/CopilotKit#776)、Web Bot Auth(CopilotKit#775)、 headed 浏览器与住宅代理(CopilotKit#772)、admin 审计 CSV 导出(CopilotKit#751)、 v0.2.0(CopilotKit#768)等。 合并要点: - drizzle 迁移:上游 0053-0055 重编号为 0084-0086,快照按上游增量 叠加我方 0083 合成,journal 时间戳在 0083 后递增;0076 快照缺失 为合并前遗留,保持原样。 - createApp 尾参并入上游 identity/identityGithubCallback,两个按位 装配的测试(self-host-banner、identity-app-wiring)改为从尾部计数。 - UI 冲突取上游重写版;我方 i18n 键补进 settings/admin locale; billing/openConnector/craft/workshop/marketplace 全部保留。 - agent-computer/bun.lock 重装再生(web-bot-auth 依赖)。 - 删除上游已删的 agent-dialog/inbox/bots.$agentId 与遗留损坏的 mobile-links.test.ts。 验证:typecheck 全绿;vite build 通过;e2e 43/43(本地起服务); 迁移 journal/identity/billing 集成测试与合并前基线一致(无新增失败, 剩余失败均为合并前遗留或本机环境项:Appium 模拟器、VPN、日期腐化)。 Co-Authored-By: Claude Code <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Admin > Audit was a read-only screen: the only way to review the trail was to look at it. This adds the missing take-out path plus query-parity fixes in the same admin surface:
GET /api/admin/audit-events?format=csvanswers the same filtered query (eventType,actorUserId,initiatorKind,targetType,targetId,from,to) as RFC 4180 CSV, with an Export CSV button on the Audit page that downloads the page's current filter.GET /api/admin/enterprise/models/usage?days=andGET /api/admin/enterprise/actions?limit=usedNumber(raw) || default, so?days=abc,?days=12abc,?limit=3.9silently returned default views while the audit/channel/people lists answer 400. Both now parse strictly (400 naming the parameter, clamp 1..365 / 1..500), matchingparsePageLimit.Why
A compliance pull, an incident timeline, or a count of what policy refused had nowhere to go — admins could only screenshot the table. The export unblocks evidence collection, and the strict parsing closes a silent-coercion inconsistency where a typo returned a plausible-looking wrong page.
What's in it
server/src/audit.ts:AUDIT_EXPORT_COLUMNS,auditEventsToCsv(RFC 4180 escaping, decision/bot columns, redacted payload as one JSON column),readAuditExportRows(walks matching pages via the same reader the JSON list uses; ignores list paging; caps at 5,000 rows and reports truncation).server/src/app.ts:?format=csvbranch withtext/csv+Content-Disposition: attachment,X-Audit-Export-Truncatedheader when capped, 400 on unknownformat. JSON path untouched.server/src/admin/routes.ts: exported pureparseEnterpriseDays/parseEnterpriseActionsLimitwired into both GETs (400s at the edge; store clamps stay as defence in depth).app/src/lib/audit/queries.ts+audit.tsx:auditExportUrl(search)(filter travels, paging dropped, strayformatreplaced) and an Export button with loading/error states.docs/architecture.md: short "Taking the trail out" subsection.server/tests/audit-export.test.ts(serializer, collector incl. truncation, route: headers/body/400s/JSON-unchanged),server/tests/enterprise-list-query-validation.test.ts(defaults, clamps, 400 cases),app/tests/audit-export-url.test.ts(filter/paging/format handling).Verification (all run locally, all green)
bunx biome lint --error-on-warnings: clean on all 8 touched source/test files.bun run --filter server typecheckandbun run --filter app typecheck: both exit 0.bun installwas needed in this checkout before tests could resolve workspace deps (pre-existing, unrelated to this change). No dependencies added or changed by this PR.Original work for this repo: no open issue or PR covers audit export (checked open issues/PRs before starting); branch is fresh off current
upstream/main(17831b2) with nothing else on it.