Skip to content

feat: ADR-0011 PR-E4 — chat-runner OAuth 削除 + token 注入#33

Merged
shomatan merged 2 commits into
mainfrom
feat/oauth-cleanup-pr-e4
May 2, 2026
Merged

feat: ADR-0011 PR-E4 — chat-runner OAuth 削除 + token 注入#33
shomatan merged 2 commits into
mainfrom
feat/oauth-cleanup-pr-e4

Conversation

@shomatan
Copy link
Copy Markdown
Contributor

@shomatan shomatan commented May 2, 2026

Summary

ADR-0011 PR-E4: chat-runner から OAuth フロー関連を全削除し、buildMcpServers が FileSystemOAuthStore から token を読んで MCP HTTP transport の Authorization header に注入する形に切替える。AuthRequestCard を chat 文脈から切り離して project settings の MCP server 行に配置し、UI 起点の Connect ボタンとして再構成する。

  • schema: McpServerConfig.oauth を required 化、auth_request ChatBlock 型を削除
  • chat-runner: OAuth 関連 ~250 行削除 (runOAuthCallback / handleAuthToolResult / auth-detector / TurnState.stashedAuthUses / chat_auth_request event)
  • buildMcpServers: oauthStore 引数追加 + Authorization header 注入 + expiresAt チェック
  • AuthRequestCard: chat → mcp ディレクトリに移動、prop signature 簡素化、project-settings-dialog に埋め込み

ADR-0011 ロードマップ進捗

主な変更点

core/schema

  • McpServerConfig.oauth を required (PR-E1 で optional 導入、本 PR で必須化)
  • ChatBlockSchema から auth_request 型を削除
  • 後方互換: 不要 (PoC 段階、既存 YAML は手動編集が必要)

ai-engine

  • auth-detector.ts ファイル削除 + テスト削除
  • chat-runner.ts: runOAuthCallback, handleAuthToolResult, findLatestPendingAuthRequest, parseAuthToolName 経路、TurnState.stashedAuthUses をすべて削除
  • server.ts: oauth_callback WS message 経路と ChatOAuthCallbackSchema を削除、ChatRunner / runAgentoauthStore を注入
  • stream.ts: chat_auth_request event 型を削除
  • mcp/build-mcp-servers.ts: oauthStore deps 追加 + async 化、token を Authorization: <tokenType> <accessToken> で header 注入。expiresAt が過去なら無視 (codex Major 対応)

frontend

  • lib/store.ts: chat_auth_request handler / sendOAuthCallback action を削除
  • lib/ws.ts: sendOAuthCallback を削除
  • components/chat/chat-message.tsx: auth_request branch / AuthRequestCard import を削除
  • components/{chat → mcp}/auth-request-card.tsx: prop signature を block: AuthRequestBlock{ mcpServerId, mcpServerLabel } に refactor
  • components/dialog/project-settings-dialog.tsx: oauth.clientId 入力欄を追加、保存済み + 編集なし + clientId 入力済 のとき AuthRequestCard を埋め込み表示

codex セカンドオピニオン Major 対応

  1. 期限切れトークンの扱い: buildMcpServers で expiresAt < now ならトークンを無視 (header 無し)。期限切れを盲目的に注入すると 401 が AI tool 失敗として埋もれて UI に通知できない問題を回避
  2. isOAuthConnectable の比較範囲: 個別フィールド比較から JSON.stringify による全フィールド一致比較に変更 (options 編集等の見落とし防止)
  3. retrograde guard: 外部 MCP tool_use テストに chat_auth_request event が emit されないことを assert (旧経路の誤再導入を CI で検知)

Test plan

  • core 94 / storage 97 / ai-engine 235 / frontend 280 すべて pass
  • typecheck (core / storage / ai-engine / frontend) clean
  • biome lint clean (3 件の warning は本 PR 由来ではない既存の指摘)
  • 実環境で OAuth フロー: project settings で clientId 入力 → 保存 → Connect ボタン → 別タブ承認 → 自動完了 → chat で Atlassian tool 利用可能 (PR-E5 の E2E で扱う)

既知の限界 (PR-E5 で扱う)

  • token expiry 自動 refresh は未実装 (現状: 期限切れ → header 無し → MCP 401 → ユーザーが Settings から再 Connect)
  • E2E テスト未整備
  • ドキュメント (CLAUDE.md / README) 未更新

Summary by CodeRabbit

リリースノート

  • 新機能

    • OAuth トークンが MCP サーバーリクエストに自動的に注入されるようになりました
  • リファクタリング

    • OAuth 認証フローがチャット WebSocket からオーケストレーターと専用ハンドラーに移行されました
    • MCP サーバーの OAuth クライアント ID 設定が必須になりました
    • チャットに認証リクエスト通知が表示されなくなりました

…+ token 注入

ADR-0011 PR-E4: chat-runner から OAuth フロー関連を全削除し、buildMcpServers が
FileSystemOAuthStore から token を読んで MCP HTTP transport の Authorization header
に注入する形に切替える。AuthRequestCard を chat 文脈から切り離して project settings
の MCP server 行に配置し、UI 起点の Connect ボタンとして再構成する。

core (schema):
- McpServerConfig.oauth を required 化 (PR-E1 で optional 導入、本 PR で必須化)
- ChatBlockSchema から auth_request 型を削除

ai-engine:
- chat-runner.ts: ~250 行削除 (runOAuthCallback / handleAuthToolResult /
  findLatestPendingAuthRequest / parseAuthToolName 経路 / TurnState.stashedAuthUses)
- auth-detector.ts: ファイル削除
- server.ts: oauth_callback WS message 経路と ChatOAuthCallbackSchema を削除
- stream.ts: chat_auth_request event 型を削除
- mcp/build-mcp-servers.ts: oauthStore deps 追加 + async 化、token を Authorization
  header に注入。expiresAt が過去なら無視 (codex Major 対応)
- agent-runner.ts: deps に oauthStore 追加

frontend:
- lib/store.ts: chat_auth_request handler / sendOAuthCallback action を削除
- lib/ws.ts: sendOAuthCallback を削除
- components/chat/chat-message.tsx: auth_request branch / AuthRequestCard import を削除
- components/{chat → mcp}/auth-request-card.tsx: prop signature を
  `block: AuthRequestBlock` から `{ mcpServerId, mcpServerLabel }` に refactor、
  ディレクトリも mcp/ に移動 (chat 文脈非依存)
- components/dialog/project-settings-dialog.tsx: oauth.clientId 入力欄を追加し、
  保存済み + 編集なし + clientId 入力済 のとき AuthRequestCard を埋め込み表示

codex セカンドオピニオン Major 対応:
1. 期限切れトークンの扱い: buildMcpServers で expiresAt を確認し過去なら null 扱い
2. isOAuthConnectable: 全フィールド比較 (JSON.stringify) で options 編集も検知
3. retrograde guard: 外部 MCP tool_use テストに `chat_auth_request` event が emit
   されないことを assert (旧経路の誤再導入を CI で検知)

テスト:
- core: 94 / storage: 97 / ai-engine: 235 / frontend: 280 すべて pass
- 削除: chat-runner.test.ts の auth_request 変換 describe (~270 行)、auth-detector.test.ts
- 追加: build-mcp-servers expiry / token-type 注入 / クロス config テスト
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 2, 2026

Warning

Rate limit exceeded

@shomatan has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 51 minutes and 43 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: fc4e991a-c9c8-4aeb-8aa4-81c74233d332

📥 Commits

Reviewing files that changed from the base of the PR and between 77c3562 and 2d0de6e.

📒 Files selected for processing (2)
  • packages/frontend/src/components/dialog/project-settings-dialog.test.tsx
  • packages/frontend/src/components/dialog/project-settings-dialog.tsx
📝 Walkthrough

Walkthrough

OAuth authorization flow transitions from in-chat request/callback handling to route handler–driven orchestration with pre-computed Authorization headers injected into MCP server configurations. Token storage, schema requirements, and component integrations are updated accordingly.

Changes

OAuth Authorization Flow Refactor

Layer / File(s) Summary
Data Shape
packages/core/src/schema.ts, packages/core/src/schema.test.ts
McpServerConfigSchema.oauth becomes required (no longer optional); ChatBlockSchema removes the auth_request union member; test fixtures updated to include oauth: { clientId } entries.
Core Implementation
packages/ai-engine/src/auth-detector.ts, packages/ai-engine/src/auth-detector.test.ts
Deletes entire auth-detector module including parseAuthToolName(), extractAuthUrl(), and AuthToolNameMatch interface (OAuth flow detection no longer happens in chat context).
Token Injection
packages/ai-engine/src/mcp/build-mcp-servers.ts, packages/ai-engine/src/mcp/build-mcp-servers.test.ts
buildMcpServers becomes async, accepts oauthStore dependency, reads per-server tokens, validates expiration via expiresAt, and conditionally injects Authorization: <tokenType> <accessToken> headers; test coverage expanded to verify token presence/expiration/injection scenarios.
Runner Integration
packages/ai-engine/src/chat-runner.ts, packages/ai-engine/src/agent-runner.ts, packages/ai-engine/src/chat-runner.test.ts, packages/ai-engine/src/agent-runner.test.ts
ChatRunnerDeps and RunAgentDeps require oauthStore field; startQueryInternal() and runAgent() pass oauthStore into buildMcpServers; OAuth callback generator runOAuthCallback() removed from ChatRunner; in-chat auth_request conversion logic removed; all test invocations now instantiate and pass FileSystemOAuthStore.
Event & Message Stream
packages/ai-engine/src/stream.ts
Removes chat_auth_request event variants (pending/completed/failed) from ChatEvent union; adds ADR-0011/PR-E4 comment indicating OAuth completion is routed through handler instead of WS events.
Server Wiring
packages/ai-engine/src/server.ts
Constructs FileSystemOAuthStore and passes it into both runAgent() and ChatRunner instantiation; removes WebSocket oauth_callback message type handling, validation schema, and delegation to runner.runOAuthCallback(); updates ADR comments clarifying OAuth is handled by Route Handler outside WS.
Frontend Schema & Routes
packages/frontend/src/app/api/projects/[id]/mcp/[mcpServerId]/oauth/route.ts, packages/frontend/src/app/api/projects/[id]/mcp/[mcpServerId]/oauth/route.test.ts, packages/frontend/src/app/api/projects/[id]/route.test.ts
Route assumes server.oauth is required (removes 400 guard for missing oauth); test helpers and fixtures updated so MCP servers always include oauth: { clientId } configuration; project patch tests use oauth payloads instead of legacy auth shapes.
Settings Dialog & Auth UI
packages/frontend/src/components/dialog/project-settings-dialog.tsx, packages/frontend/src/components/dialog/project-settings-dialog.test.tsx
Adds oauth.clientId input field for each MCP server; introduces isOAuthConnectable() guard to display AuthRequestCard only when client ID is saved and non-empty; updates help text to reflect OAuth 2.1 flow managed by Tally process; removes legacy auth/secret input support.
Auth Request Card Refactor
packages/frontend/src/components/mcp/auth-request-card.tsx, packages/frontend/src/components/mcp/auth-request-card.test.tsx
Changes from block-based ({ block: AuthRequestBlock }) to prop-based ({ mcpServerId, mcpServerLabel }) API; removes dependency on ChatBlock; computes OAuth orchestrator URL from projectId + mcpServerId; test fixtures and render calls updated to use new props.
Chat Message Rendering
packages/frontend/src/components/chat/chat-message.tsx
Removes AuthRequestCard import and eliminates block.type === 'auth_request' rendering branch; auth_request blocks now fall through to return null.
Store & WS Client APIs
packages/frontend/src/lib/store.ts, packages/frontend/src/lib/ws.ts
Removes sendOAuthCallback(mcpServerId, callbackUrl) method from CanvasState and ChatHandle interfaces; deletes applyChatEvent branch for chat_auth_request event handling; WS client no longer returns OAuth callback sender.
Test Fixtures & Assertions
packages/core/src/schema.test.ts
Updates McpServerConfigSchema fixtures to include oauth: { clientId } and assertions that oauth is required; replaces legacy auth_request block acceptance test with rejection test; updates ProjectSchema and ProjectMetaSchema fixtures for MCP server entries.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Frontend Client
    participant Settings as ProjectSettingsDialog
    participant AuthCard as AuthRequestCard
    participant Route as OAuth Route Handler<br/>/api/.../oauth
    participant OAuthRegistry as OAUTH_REGISTRY<br/>(External Provider)
    participant Tally as Tally Core<br/>(Token Storage)

    Client->>Settings: Enter OAuth Client ID
    Settings->>AuthCard: Render (when clientId saved)
    AuthCard->>Route: POST /oauth (start flow)
    Route->>OAuthRegistry: Redirect to provider
    OAuthRegistry->>Route: Authorization code
    Route->>Tally: Store access token
    AuthCard->>Route: Poll GET /oauth
    Route->>AuthCard: Return completed status
    AuthCard->>Client: Show "認証済"
Loading
sequenceDiagram
    participant Chat as ChatRunner
    participant Store as FileSystemOAuthStore
    participant Builder as buildMcpServers
    participant MCPServer as MCP HTTP Server

    Chat->>Builder: buildMcpServers(configs, oauthStore)
    Builder->>Store: read(mcpServerId) for each config
    Store-->>Builder: { accessToken, tokenType, expiresAt }
    Builder->>Builder: Check expiration vs Date.now()
    alt Token valid & not expired
        Builder->>Builder: Inject Authorization header
    else Token missing or expired
        Builder->>Builder: Skip Authorization header
    end
    Builder-->>Chat: MCP configs with headers
    Chat->>MCPServer: Connect with Authorization
    MCPServer-->>Chat: Authenticated response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 69.23% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed PRタイトルは ADR-0011 PR-E4 対応のOAuth関連変更を的確に要約しており、主要な変更(chat-runner OAuth削除 + token注入)を明確に表現しています。
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/oauth-cleanup-pr-e4

Tip

💬 Introducing Slack Agent: Turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get your free trial and get 200 agent minutes per Slack user (a $50 value).


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 51 minutes and 43 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
packages/core/src/schema.ts (1)

385-410: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

auth_request の即時削除で既存チャット履歴が読めなくなります。

ChatMessageSchema / ChatThreadSchema はこの union をそのまま読むので、以前に永続化した auth_request block を含む chat は parse 失敗になります。project.yaml 側と違って read-time の互換処理が無いので、少なくとも legacy parser を残すか、読み込み時 migration を先に入れたいです。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/schema.ts` around lines 385 - 410, The ChatBlockSchema
removal of the old auth_request variant will break parsing of persisted chats
(ChatMessageSchema / ChatThreadSchema) that contain legacy auth_request blocks;
restore backward compatibility by adding either (a) a legacy union member for
auth_request in ChatBlockSchema (or a z.union fallback) or (b) implement a
read-time migration that transforms legacy auth_request blocks to the new
representation before parsing; update the discriminated union logic in
ChatBlockSchema and the code paths that call ChatMessageSchema/ChatThreadSchema
to apply the migration/conversion so existing persisted chat data can be parsed
without errors.
packages/frontend/src/app/api/projects/[id]/route.test.ts (1)

121-139: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

http URL hardening の検証が偽陽性になっています。

この payload は oauth を入れていないので、今は URL 制約ではなく McpServerConfigSchema.oauth 必須化で 400 になります。これだと http://example.com 拒否の回帰を拾えません。

修正例
           {
             id: 'a',
             name: 'A',
             kind: 'atlassian',
             url: 'http://example.com/mcp',
+            oauth: { clientId: 'cid' },
             options: { maxChildIssues: 30, maxCommentsPerIssue: 5 },
           },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/frontend/src/app/api/projects/`[id]/route.test.ts around lines 121 -
139, The test currently fails due to missing McpServerConfigSchema.oauth causing
a 400 before URL validation; update the test payload in the PATCH call to
include a valid oauth object for the mcpServers entry (so schema validation
passes) while keeping url: 'http://example.com/mcp' to trigger the HTTP
non-loopback URL rejection. Locate the test case using the mcpServers array in
this file (referenced by the PATCH helper, projectId and
McpServerConfigSchema.oauth) and add a minimal valid oauth field appropriate for
the atlassian kind so the response check (expect(res.status).toBe(400)) reflects
the URL hardening check instead of missing oauth validation.
packages/ai-engine/src/chat-runner.ts (1)

281-312: ⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

OAuth トークンの更新が既存の ChatRunner に反映されません。

buildMcpServers({ oauthStore }) はここで一度しか実行されませんが、ensureQuery() は生きている subprocess を turn 間で再利用します。つまり project settings で接続/再接続しても、この runner は古い Authorization ヘッダのまま次ターンを処理し続けます。expiresAt の無視も起動時にしか効かないので、設定画面で「認証完了」になっても同じセッションでは外部 MCP が未認証/期限切れのままになるはずです。OAuth state の変更時に query を破棄して再生成するか、turn ごとに MCP 設定を再構築する仕組みが必要です。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-engine/src/chat-runner.ts` around lines 281 - 312,
ensureQuery/startQueryInternal builds MCP servers once (via buildMcpServer and
buildMcpServers) and caches external configs (cachedExternalConfigById), so
OAuth token updates in oauthStore are not picked up for long‑lived ChatRunner
sessions; change the logic to detect OAuth state changes and recreate the query
or rebuild MCPs: either invalidate/tearDown the existing query when oauthStore
or externalConfigs (including expiresAt/token) change before reusing
ensureQuery, or move the MCP construction (buildMcpServer/buildMcpServers) out
of startQueryInternal into a per-turn refresh step so each turn re-reads
oauthStore and rebuilds Authorization headers; implement detection using the
same keys stored in cachedExternalConfigById or a version/hash of oauthStore and
clear ensureQueryInflight/query via tearDownQuery when a change is detected.
🧹 Nitpick comments (1)
packages/ai-engine/src/chat-runner.test.ts (1)

619-677: 🏗️ Heavy lift

MCP/OAuth 系のケースは別 test module に分割したいです。

このファイルはすでに 1,200 行超で、今回の PR-E4 / Task 11-13 の追加で ChatRunner 本体、prompt 組み立て、外部 MCP 統合の責務がさらに混ざっています。ここは chat-runner.mcp.test.ts のような専用ファイルへ切り出した方が保守しやすいです。

As per coding guidelines, "Keep individual files under 500 lines; split larger files into multiple modules".

Also applies to: 680-1081

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/ai-engine/src/chat-runner.test.ts` around lines 619 - 677, This test
file contains MCP/OAuth-specific tests that should be extracted into a dedicated
module to keep files under ~500 lines; create a new test file (e.g.,
chat-runner.mcp.test.ts) and move the PR-E4 test and the block noted (the
MCP/OAuth-related tests spanning the comment's referenced region) into it.
Ensure the new file imports the same helpers and classes used by the moved tests
(mkdtempSync, tmpdir, rmSync, path, FileSystemProjectStore,
FileSystemOAuthStore, FileSystemChatStore, ChatRunner, SdkLike, vi, etc.),
preserve the test titles and setup/teardown, and remove the moved tests from
packages/ai-engine/src/chat-runner.test.ts so the original file remains below
the size guideline. Run tests to confirm imports and mocks (e.g., querySpy)
still work after relocation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/frontend/src/components/dialog/project-settings-dialog.tsx`:
- Around line 44-55: isOAuthConnectable currently does a JSON.stringify equality
between saved and entry, but entry is a McpServerEntry that includes
runtime-only _uid so the comparison always fails; change the comparison to omit
ephemeral fields (at least _uid) from entry before stringifying or compare only
the relevant persisted fields (e.g. id, oauth, etc.). Update the function
isOAuthConnectable to derive a cleanedEntry (or a shallow pick of persisted
keys) from entry, then compare JSON.stringify(saved) ===
JSON.stringify(cleanedEntry) so saved matches unedited rows.

---

Outside diff comments:
In `@packages/ai-engine/src/chat-runner.ts`:
- Around line 281-312: ensureQuery/startQueryInternal builds MCP servers once
(via buildMcpServer and buildMcpServers) and caches external configs
(cachedExternalConfigById), so OAuth token updates in oauthStore are not picked
up for long‑lived ChatRunner sessions; change the logic to detect OAuth state
changes and recreate the query or rebuild MCPs: either invalidate/tearDown the
existing query when oauthStore or externalConfigs (including expiresAt/token)
change before reusing ensureQuery, or move the MCP construction
(buildMcpServer/buildMcpServers) out of startQueryInternal into a per-turn
refresh step so each turn re-reads oauthStore and rebuilds Authorization
headers; implement detection using the same keys stored in
cachedExternalConfigById or a version/hash of oauthStore and clear
ensureQueryInflight/query via tearDownQuery when a change is detected.

In `@packages/core/src/schema.ts`:
- Around line 385-410: The ChatBlockSchema removal of the old auth_request
variant will break parsing of persisted chats (ChatMessageSchema /
ChatThreadSchema) that contain legacy auth_request blocks; restore backward
compatibility by adding either (a) a legacy union member for auth_request in
ChatBlockSchema (or a z.union fallback) or (b) implement a read-time migration
that transforms legacy auth_request blocks to the new representation before
parsing; update the discriminated union logic in ChatBlockSchema and the code
paths that call ChatMessageSchema/ChatThreadSchema to apply the
migration/conversion so existing persisted chat data can be parsed without
errors.

In `@packages/frontend/src/app/api/projects/`[id]/route.test.ts:
- Around line 121-139: The test currently fails due to missing
McpServerConfigSchema.oauth causing a 400 before URL validation; update the test
payload in the PATCH call to include a valid oauth object for the mcpServers
entry (so schema validation passes) while keeping url: 'http://example.com/mcp'
to trigger the HTTP non-loopback URL rejection. Locate the test case using the
mcpServers array in this file (referenced by the PATCH helper, projectId and
McpServerConfigSchema.oauth) and add a minimal valid oauth field appropriate for
the atlassian kind so the response check (expect(res.status).toBe(400)) reflects
the URL hardening check instead of missing oauth validation.

---

Nitpick comments:
In `@packages/ai-engine/src/chat-runner.test.ts`:
- Around line 619-677: This test file contains MCP/OAuth-specific tests that
should be extracted into a dedicated module to keep files under ~500 lines;
create a new test file (e.g., chat-runner.mcp.test.ts) and move the PR-E4 test
and the block noted (the MCP/OAuth-related tests spanning the comment's
referenced region) into it. Ensure the new file imports the same helpers and
classes used by the moved tests (mkdtempSync, tmpdir, rmSync, path,
FileSystemProjectStore, FileSystemOAuthStore, FileSystemChatStore, ChatRunner,
SdkLike, vi, etc.), preserve the test titles and setup/teardown, and remove the
moved tests from packages/ai-engine/src/chat-runner.test.ts so the original file
remains below the size guideline. Run tests to confirm imports and mocks (e.g.,
querySpy) still work after relocation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 25026917-c314-4bbb-8f3a-09225141e22e

📥 Commits

Reviewing files that changed from the base of the PR and between 3f8c60b and 77c3562.

📒 Files selected for processing (22)
  • packages/ai-engine/src/agent-runner.test.ts
  • packages/ai-engine/src/agent-runner.ts
  • packages/ai-engine/src/auth-detector.test.ts
  • packages/ai-engine/src/auth-detector.ts
  • packages/ai-engine/src/chat-runner.test.ts
  • packages/ai-engine/src/chat-runner.ts
  • packages/ai-engine/src/mcp/build-mcp-servers.test.ts
  • packages/ai-engine/src/mcp/build-mcp-servers.ts
  • packages/ai-engine/src/server.ts
  • packages/ai-engine/src/stream.ts
  • packages/core/src/schema.test.ts
  • packages/core/src/schema.ts
  • packages/frontend/src/app/api/projects/[id]/mcp/[mcpServerId]/oauth/route.test.ts
  • packages/frontend/src/app/api/projects/[id]/mcp/[mcpServerId]/oauth/route.ts
  • packages/frontend/src/app/api/projects/[id]/route.test.ts
  • packages/frontend/src/components/chat/chat-message.tsx
  • packages/frontend/src/components/dialog/project-settings-dialog.test.tsx
  • packages/frontend/src/components/dialog/project-settings-dialog.tsx
  • packages/frontend/src/components/mcp/auth-request-card.test.tsx
  • packages/frontend/src/components/mcp/auth-request-card.tsx
  • packages/frontend/src/lib/store.ts
  • packages/frontend/src/lib/ws.ts
💤 Files with no reviewable changes (4)
  • packages/frontend/src/lib/ws.ts
  • packages/ai-engine/src/auth-detector.ts
  • packages/frontend/src/components/chat/chat-message.tsx
  • packages/ai-engine/src/auth-detector.test.ts

Comment thread packages/frontend/src/components/dialog/project-settings-dialog.tsx
CR Major 対応: McpServerEntry は UI ローカルの `_uid` を持つが、saved 側 (永続化済み
McpServerConfig[]) には _uid が無い。JSON.stringify による全フィールド比較が _uid の
差分で常に false になり、Connect ボタンが一度も出ないバグだった。

entry から _uid を destructure で剥がしてから比較するよう修正。

回帰テスト 2 件追加:
- 保存済み + clientId 入力済 → Connect ボタンが描画される
- name を編集すると Connect ボタンが消えてヒント文に切り替わる
@shomatan shomatan merged commit 907e623 into main May 2, 2026
2 checks passed
@shomatan shomatan deleted the feat/oauth-cleanup-pr-e4 branch May 2, 2026 21:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant