Hacktoberfest 2026:メンテナが10月に向けて印を付けた、オープンで初心者向けの issue。 Hacktoberfest の issue を見る

🎃 Export the audit log as CSV or JSON from /logs

オープン
#998 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

まだ誰も着手していません。

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
22/100
issue の種類
機能追加
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
typescript

調査の方向性

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.

索引モデルが issue の本文から書いたものです。

説明

enhancement hacktoberfest help wanted

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 than INVOCATION_RETENTION_DAYS (default 90) are deleted and payloads older than INVOCATION_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 under ee/. 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 ADMIN only (@Roles('ADMIN') with RolesGuard, the pattern on site-settings.controller.ts:111-112). Other roles keep reading /logs as today but get no bulk download. Rows are always scoped to the caller's organization. If the JWT carries no organizationId, 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

  1. Shared filter builder: move the where construction out of getRecentInvocations (audit.service.ts:302-345) into one helper used by the list and the export, and add from / to on createdAt (ISO date or datetime; from inclusive, to exclusive). The list endpoint gets from/to too.
  2. Endpoint: GET /api/audit/invocations/export?format=csv|json with the list filters (status, search, connectorId, mcpServerId, toolId, from, to) plus payloads=true|false (default false). Headers: Content-Type: text/csv; charset=utf-8 or application/json, and Content-Disposition: attachment; filename="anythingmcp-audit-<from>-<to>.<ext>".
  3. 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 at AUDIT_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 a truncated: true field) so the UI can say "narrow the date range". For JSON, write an array incrementally or NDJSON; pick one and document it.
  4. Columns (same names in CSV and JSON): createdAt (ISO 8601 UTC), status, tool, connector, connectorType, mcpServer, userEmail, authMethod and apiKeyName (both parsed from clientInfo), durationMs, repeatCount, error; with payloads=true also input and output (JSON strings in CSV). Keep repeatCount: one stored row can stand for many identical failures (audit.service.ts:12-18).
  5. 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.
  6. UI: on /logs, rename exportButton to 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() in lib/api.ts:27-57 always parses JSON, so add a separate client helper that uses fetch + blob() and an object URL, like handleExportAll on 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() and getRecentInvocations() (the includes give tool, connector, user and server names).
  • packages/backend/prisma/schema.prisma:678-718: ToolInvocation (clientInfo is a JSON string; repeatCount).
  • packages/backend/src/auth/roles.guard.ts:11 and packages/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 and from/to build the expected where; 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=false omits input/output.
  • EDITOR and VIEWER get 403 from the export endpoint; a JWT without organizationId gets 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* like mobile.spec.ts): an admin sees the Export menu and the request carries the active filters and dates; a viewer does not see it. Run with cd packages/frontend && npm run test:e2e.
  • docs/api-reference.md: export endpoint documented, toolName example removed, from/to documented, 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.

主要言語
TypeScript
スター
856
フォーク
82
平均マージ
8時間 27分
マージ済み PR(30日)
104

環境構築

このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

HelpCode-ai/anythingmcp のほかの issue

HelpCode-ai/anythingmcp の issue をすべて見る

似ている issue

TypeScript の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。