🎃 Export the audit log as CSV or JSON from /logs
Maintainer thường phản hồi trong vòng 1 ngày
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức phù hợp với người mới
- 22/100
- Loại issue
- Tính năng
- Độ rõ ràng
- Đặc tả rõ ràng
- Mức độ hoạt động
- Sôi nổi
- Công nghệ
- typescript
- Lĩnh vực
- api, backend, documentation, frontend, security
Hướng nghiên cứu
Start with getRecentInvocations and orgScope() in packages/backend/src/audit/audit.service.ts, and the list endpoint in audit.controller.ts, to see how the where filters are built today. Then look at the admin-only guard pattern in site-settings.controller.ts. Done means the export endpoint streams batches under the row cap, returns 403 for non-admins and for a missing organizationId, and the audit specs and Playwright test pass.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
Part of the October Challenge #997.
Why
Admins regularly need the tool-call history outside the product: for a security review, to attach to a support ticket, to load into a spreadsheet or a SIEM, or to keep it beyond the retention window. Today the Audit Log page (/logs) shows 50 rows per page and offers no download. The only way out is paging through GET /api/audit/invocations by hand. GitHub's audit log, Auth0 and Grafana all offer CSV and JSON export of the filtered view.
What already exists: the page filters by status, tool/connector search, connector and MCP server (logs/page.tsx:116-134), and the API supports the same filters plus limit/offset (audit.controller.ts:13-37). There is no date filter and no export. The header button passed to AppShell as exportButton (logs/page.tsx:183-207) is only a Refresh button with a misleading variable name. docs/api-reference.md:226-253 documents toolName, from and to filters that the API does not have, and a stats response (last24h, last7d, total) that does not match getStats() (invocations24h, errors24h, invocations7d, totalInvocations).
Self-hosted vs Cloud
- Self-hosted: enabled in Community and Business. No
ee/code. There is no retention job on self-hosted, so an export can cover the whole history of the organization. - Cloud (
DEPLOYMENT_MODE=cloud): enabled. Rows older thanINVOCATION_RETENTION_DAYS(default 90) are deleted and payloads older thanINVOCATION_PAYLOAD_RETENTION_DAYS(default 14) are cut to an excerpt (ee/cloud/kg-cron.service.ts:372,:407), so an export only contains what is still stored. Say so in a tooltip next to the button. Do not change anything underee/. The export must be streamed in batches: an organization can have hundreds of thousands of rows, and loading them in one query would put the shared backend's heap at risk. - Who can use it: org
ADMINonly (@Roles('ADMIN')withRolesGuard, the pattern onsite-settings.controller.ts:111-112). Other roles keep reading/logsas today but get no bulk download. Rows are always scoped to the caller's organization. If the JWT carries noorganizationId, return 403:orgScope()returns{}(no filter) for a missing org (audit.service.ts:297-300), and an export must never fall back to all rows.
What to build
- Shared filter builder: move the
whereconstruction out ofgetRecentInvocations(audit.service.ts:302-345) into one helper used by the list and the export, and addfrom/tooncreatedAt(ISO date or datetime;frominclusive,toexclusive). The list endpoint getsfrom/totoo. - Endpoint:
GET /api/audit/invocations/export?format=csv|jsonwith the list filters (status,search,connectorId,mcpServerId,toolId,from,to) pluspayloads=true|false(defaultfalse). Headers:Content-Type: text/csv; charset=utf-8orapplication/json, andContent-Disposition: attachment; filename="anythingmcp-audit-<from>-<to>.<ext>". - Streaming: read in batches of 1,000 with a keyset cursor on
(createdAt desc, id desc)and write each batch to the response (@Res()), never collecting all rows in memory. Cap one export atAUDIT_EXPORT_MAX_ROWS(default 100,000). When the cap is reached, end the file cleanly and add a final marker (a last CSV comment line or atruncated: truefield) so the UI can say "narrow the date range". For JSON, write an array incrementally or NDJSON; pick one and document it. - Columns (same names in CSV and JSON):
createdAt(ISO 8601 UTC),status,tool,connector,connectorType,mcpServer,userEmail,authMethodandapiKeyName(both parsed fromclientInfo),durationMs,repeatCount,error; withpayloads=truealsoinputandoutput(JSON strings in CSV). KeeprepeatCount: one stored row can stand for many identical failures (audit.service.ts:12-18). - CSV safety: RFC 4180 quoting (quotes, commas, newlines), UTF-8 with BOM so Excel shows umlauts correctly, and formula-injection protection: prefix a cell that starts with
=,+,-,@, tab or carriage return with'. Tool arguments and upstream errors are user- and vendor-controlled text. - UI: on
/logs, renameexportButtonto what it is and add an "Export" menu next to Refresh (CSV, JSON, and an "Include input and output" option), shown to admins only (useAuth().user.role). Add a From / To date range to the toolbar (logs/page.tsx:210-267) that drives both the list and the export.request()inlib/api.ts:27-57always parses JSON, so add a separate client helper that usesfetch+blob()and an object URL, likehandleExportAllon the Connectors page (connectors/page.tsx:139-160).
Where to look
packages/backend/src/audit/audit.controller.ts:13-37: list endpoint and its filters.packages/backend/src/audit/audit.service.ts:297-345:orgScope()andgetRecentInvocations()(the includes give tool, connector, user and server names).packages/backend/prisma/schema.prisma:678-718:ToolInvocation(clientInfois a JSON string;repeatCount).packages/backend/src/auth/roles.guard.ts:11andpackages/backend/src/settings/site-settings.controller.ts:111-112: admin-only guard pattern.packages/backend/src/ee/cloud/kg-cron.service.ts:372,:407: Cloud payload trim and retention (read only).packages/frontend/src/app/logs/page.tsx:83-207: state, filters, fetch, header actions.packages/frontend/src/lib/api.ts:753-765:audit.invocations()client.packages/frontend/src/components/ui/action-menu.tsx: dropdown for the menu.docs/api-reference.md:219-253: Audit section to correct and extend.
Acceptance criteria
- Unit specs next to the service (
cd packages/backend && npm test): filters andfrom/tobuild the expectedwhere; another organization's rows never appear; CSV escaping (quotes, newlines, a cell starting with=); the row cap ends the file with the truncation marker;payloads=falseomitsinput/output. -
EDITORandVIEWERget 403 from the export endpoint; a JWT withoutorganizationIdgets 403. - Exporting 50,000 seeded rows keeps backend memory flat (describe how you checked in the PR).
- The CSV opens in LibreOffice or Excel with correct columns and umlauts.
- Playwright test in
packages/frontend/tests/e2e/(stub/api/audit/invocations*likemobile.spec.ts): an admin sees the Export menu and the request carries the active filters and dates; a viewer does not see it. Run withcd packages/frontend && npm run test:e2e. -
docs/api-reference.md: export endpoint documented,toolNameexample removed,from/todocumented, stats response corrected.
Out of scope
- Scheduled or emailed exports, pushing to S3 or a SIEM.
- Exporting security events or product events.
- Changing retention on Cloud or adding retention to self-hosted.
- Any change under
ee/.
Size
M (1–2 days)
How to claim
Comment "I'd like to work on this" and we'll assign you. Rules in #997.
- Ngôn ngữ chính
- TypeScript
- Star
- 856
- Fork
- 82
- Merge trung bình
- 6 giờ 49 phút
- Pull request đã merge (30 ngày)
- 152
Chuẩn bị môi trường
Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của HelpCode-ai/anythingmcp
-
Docs: document all SMTP_* and other undocumented env vars for self-hostingCó thể đã có người làm @notlakshitha đã nhận hôm nay. Đang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
HelpCode-ai/anythingmcp#1049 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue hacktoberfest
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 70/100
HelpCode-ai/anythingmcp#996 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
good first issue hacktoberfest
Độ khó 2/5 Nửa ngày Mức phù hợp với người mới 72/100
HelpCode-ai/anythingmcp#995 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
enhancement good first issue hacktoberfest help wanted
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
HelpCode-ai/anythingmcp#982 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Upload the new social previewCó thể đã có người làm @helpcodeai đã nhận hôm nay. Đang mở
HelpCode-ai/anythingmcp#1087 · 2 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Tất cả issue của HelpCode-ai/anythingmcp
Issue tương tự
-
useFragment does not require `variables` when the fragment's variables type has required fieldsĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 75/100
apollographql/apollo-client#13493 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Custom hosts written as trailing-dot FQDNs (`host.local.`) aren't detected as local backendsCó thể đã có người làm @roboomp đã nhận hôm nay. Đang mởbug prio:p2 providers triaged
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 82/100
can1357/oh-my-pi#15798 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 62/100
code-yeongyu/oh-my-openagent#10172 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
PDFCraftTool/pdfcraft#189 ·
-
Add the Yahoo chart API duplicate last-day row (yfinance#573) to incidents.md (about 1 hour)Có thể đã có người làm Có pull request liên kết đang mở hoặc đã được merge. Đang mởdata docs good first issue
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 80/100
pacocartones/market-data-sanity-checker#160 ·
Maintainer thường phản hồi trong vòng 1 ngày