🎃 Export the audit log as CSV or JSON from /logs
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 3/5
- 見積もり時間
- 1〜2日
- 初心者へのやさしさ
- 68/100
- issue の種類
- 機能追加
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- typescript
調査の方向性
Start with the list filters in packages/backend/src/audit/audit.controller.ts and orgScope()/getRecentInvocations() in audit.service.ts; then read the logs page and audit client paths listed in the issue. Run the backend tests with cd packages/backend && npm test and add the specified CSV utility tests. Done means the streamed export honors filters, admin and organization restrictions, row cap and truncation header, with the frontend button and API docs updated.
索引モデルが issue の本文から書いたものです。
説明
Part of the October Challenge #846.
Why
The Audit Log page (/logs) only lets you page through tool calls 50 at a time. Admins who need to send a compliance report, look into an incident in a spreadsheet, or attach evidence to a support ticket have nothing to download. Most API gateways and MCP platforms (Kong, Tyk, Apigee, Postman monitors) have a "download logs" button. This issue adds a streamed export that applies the filters the user already has set.
Self-hosted vs Cloud
- Self-hosted: enabled in Community and Business. Not a Business feature: do not touch
ee/. - Cloud (
DEPLOYMENT_MODE=cloud): enabled, behaves the same. Cloud is multi-tenant, so the export must always be scoped to the caller's organization: refuse with 403 whenreq.user.organizationIdis not set, and never fall back to unscoped rows. One tenant can hold millions of rows (see the comment inbound-payload.ts), so the row cap and the throttle are required. - Who can use it:
ADMINonly (@Roles('ADMIN')+RolesGuard). Every role can view the list today, but a bulk download of the whole org's call payloads is a bigger step, so it is limited to admins. Hide the button for other roles. The data is always filtered to the caller's organization.
What to build
- Backend:
GET /api/audit/invocations/export?format=csv|jsoninaudit.controller.ts. It takes the same filters as the list (status,search,connectorId,mcpServerId,toolId) plus optional ISOfrom/tooncreatedAt. - Move the
whereconstruction out ofgetRecentInvocations()into one helper (e.g.buildInvocationWhere(filters)) that both the list and the export call, so the two cannot drift apart. - Stream the response: read in batches (e.g. 1000 rows, keyset pagination on
createdAt/id, newest first) and write each batch tores. Never load everything into memory. Cap atAUDIT_EXPORT_MAX_ROWS(default50000). SendX-Export-Truncated: truewhen the cap was hit (do acountfirst). SetContent-Disposition: attachment; filename="anythingmcp-logs-YYYY-MM-DD.csv". Throttle with@Throttle({ default: { limit: 5, ttl: 60_000 } }). - Columns (only data the page already shows):
createdAt(ISO),status,durationMs,tool,connector,connectorType,mcpServer,userEmail,authMethod,apiKeyName,error. JSON additionally includes theinput/outputexcerpts exactly as stored. Do not exportintent,costMicros,usedProxy, the rawclientInfoblob, internal ids other than the invocation id, or anything else the UI does not show. - CSV safety: RFC 4180 quoting (wrap in quotes, double any
"), and escape formula injection: prefix any cell that starts with=,+,-,@, tab or CR with'. Put this in a small pure function (e.g.packages/backend/src/audit/csv.util.ts) so it can be unit-tested. JSON: either one array or NDJSON. Pick one and document it. - Frontend: an "Export" button (with a CSV/JSON choice) in the page
actionsnext to Refresh. Call it with the current filters,fetchwith the Bearer token, download the result as a Blob (same pattern asconnectors/page.tsx:139-149), and show a notice whenX-Export-Truncatedis set. Add anaudit.exportInvocations()helper inlib/api.ts. The sharedrequest()helper parses JSON, so it can't be used for the file.
Where to look
packages/backend/src/audit/audit.controller.ts:13-38: the list endpoint and its filters.packages/backend/src/audit/audit.service.ts:176-225:orgScope()andgetRecentInvocations().packages/backend/src/audit/bound-payload.ts:16:_amcp_truncatedmarker. Stored payloads are excerpts, so don't try to recover full bodies.packages/backend/src/knowledge-graph/kg.controller.ts:22,52:RolesGuard+@Roles('ADMIN')pattern.packages/backend/src/auth/login.controller.ts:137:@Throttlepattern.packages/backend/src/auth/login.controller.ts:87:@Res()usage with Express.packages/frontend/src/app/logs/page.tsx:116-134(filters),:183-207(theexportButtonvariable is actually Refresh; rename it),:204-208(actions).packages/frontend/src/app/settings/layout.tsx:54:user?.role === 'ADMIN'check.packages/frontend/src/lib/api.ts:735-747:auditclient.
Acceptance criteria
- Export applies every active filter, and only the caller's org rows are ever returned (unit test:
organizationIdis in thewhere; a missing org gives 403). - Non-admins get 403, and the button is hidden for them.
- Results are streamed in batches, the row cap is honored, and the truncation header is set.
-
csv.util.spec.tscovers quoting, newlines inside cells, and=cmd|' /C calc'!A0-style injection. -
audit.service.spec.ts/ a new controller spec covers the shared where-builder (cd packages/backend && npm test). -
docs/api-reference.mdAudit section (line 219) documents the endpoint. Also fix the existing examples at lines 226-236, which usetoolName/from/toparams the list endpoint does not support.
Out of scope
- Scheduled exports, emailing exports, S3/SIEM push.
- Exporting security events or product events.
- Changing what is stored in
tool_invocations, or the retention policy.
Size
M (1–2 days)
How to claim
Comment "I'd like to work on this" and we'll assign you. Rules in #846.
- 主要言語
- TypeScript
- スター
- 856
- フォーク
- 82
- 平均マージ
- 8時間 27分
- マージ済み PR(30日)
- 104
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
HelpCode-ai/anythingmcp のほかの issue
-
good first issue hacktoberfest
難易度 2/5 半日 初心者へのやさしさ 70/100
HelpCode-ai/anythingmcp#996 ·
メンテナーはふだん 1 日以内に返信
-
good first issue hacktoberfest
難易度 2/5 半日 初心者へのやさしさ 72/100
HelpCode-ai/anythingmcp#995 ·
メンテナーはふだん 1 日以内に返信
-
enhancement good first issue hacktoberfest help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
HelpCode-ai/anythingmcp#982 ·
メンテナーはふだん 1 日以内に返信
-
good first issue hacktoberfest
難易度 2/5 1〜3時間 初心者へのやさしさ 88/100
HelpCode-ai/anythingmcp#745 ·
メンテナーはふだん 1 日以内に返信
-
🐣 Good first issue: contribute a new MCP adapter再び着手できるかも @7k777 が 20 日前に担当しましたが、オープン中のプルリクエストはありません。 オープンenhancement good first issue hacktoberfest help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 85/100
HelpCode-ai/anythingmcp#150 · コメント 18 件 ·
メンテナーはふだん 1 日以内に返信
HelpCode-ai/anythingmcp の issue をすべて見る
似ている issue
-
area:deploy task
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
wilanis/wilanis-js#1017 ·
メンテナーはふだん 1 日以内に返信
-
documentation v2
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
modelcontextprotocol/servers#5133 ·
メンテナーはふだん 1 日以内に返信
-
budget bug feature frontend good-issue medium needs-review OSCI'26 payments
難易度 2/5 1〜3時間 初心者へのやさしさ 75/100
SatyamPandey-07/WorkSphere#5990 · コメント 1 件 ·
メンテナーはふだん 1 日以内に返信
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
lugassawan/swe-workbench#799 ·
メンテナーはふだん 1 日以内に返信
-
bug good first issue javascript
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
yukikotani231/sqlsift#326 ·
メンテナーはふだん 1 日以内に返信