Skip to content

E2EE 機能の削除と関連コードの整理#618

Open
tako0614 wants to merge 1 commit intomasterfrom
codex/remove-e2ee-directory-and-imports
Open

E2EE 機能の削除と関連コードの整理#618
tako0614 wants to merge 1 commit intomasterfrom
codex/remove-e2ee-directory-and-imports

Conversation

@tako0614
Copy link
Copy Markdown
Owner

@tako0614 tako0614 commented Aug 23, 2025

概要

  • E2EE 関連ディレクトリとチャット設定/タイトルバーコンポーネントを削除
  • 既存コンポーネントから E2EE 参照を除去し不要な状態や処理を整理
  • マイクロブログ API のキャッシュ処理を簡素化

テスト

  • deno fmt
  • deno lint (既存コードに起因するエラーあり)

https://chatgpt.com/codex/tasks/task_e_68a91a6ca8288328a0e37e92331b7a37

Summary by CodeRabbit

  • Refactor
    • チャットのE2EE/MLS機能と関連UIを削除(設定モーダル/タイトルバー含む)
    • 複数アカウントの自動トップアップ処理を削除し、アクティブアカウントのみを扱う挙動に簡素化
    • プロフィールからのチャット開始はサーバ連携なしのクライアント側状態更新みに変更
    • ユーザー情報キャッシュをメモリのみへ(永続化を廃止)
  • Style
    • 一部コードの整形・軽微な文字列表記の統一・設定ファイルの空白調整(挙動変更なし)
  • Tests
    • MLS関連のE2Eテスト群を削除

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Aug 23, 2025

Walkthrough

大規模なMLS/E2EE関連コードをクライアントから削除。チャット設定/タイトルバーUI、MLS API/ラッパー/ストレージ/フック/テストを除去。Applicationのマルチアカウント自動TopUpを廃止。ProfileのopenChatを同期・クライアント内更新へ変更。その他は軽微な整形・キャッシュ仕様(メモリ限定)・文言/空白調整。

Changes

Cohort / File(s) Summary
MLS/E2EE クライアント層の削除
app/client/src/components/e2ee/api.ts, .../e2ee/binding.ts, .../e2ee/mls_message.ts, .../e2ee/mls_test.ts, .../e2ee/mls_wrapper.ts, .../e2ee/storage.ts, .../e2ee/useMLS.ts
MLS API、型、メッセージTLV、ラッパー、ストレージ、フック、テストを全削除。公開エクスポート多数消滅。
チャットUIコンポーネント削除
app/client/src/components/chat/ChatSettingsOverlay.tsx, app/client/src/components/chat/ChatTitleBar.tsx
ルーム設定オーバーレイとチャットタイトルバーを削除。関連のエクスポートが消滅。
Profile: openChat フロー変更
app/client/src/components/Profile.tsx
openChatを非同期から同期へ。バックエンド呼び出しを排除し、ハンドル計算・検証後にクライアント状態更新のみ実施。
Application: 起動時処理の簡素化
app/client/src/components/Application.tsx
マルチアカウントのKeyPackage TopUp処理とタイマー、関連importを削除。アクティブアカウント登録とWS接続は維持。
Microblog キャッシュのメモリ化
app/client/src/components/microblog/api.ts
永続ストレージ依存を削除し、getCachedUserInfo/setCachedUserInfoをメモリ限定へ変更。関数シグネチャ更新。
軽微な整形/無機能変更
app/api/routes/posts.ts, app/client/src/components/AddServerForm.tsx, app/client/src/utils/firebase.ts, app/client/vite.config.mts
ロジック不変の整形・引用符・空白調整。

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor User as User
  participant Prof as Profile Component
  participant State as AppState
  participant Nav as Router

  User->>Prof: Click "Open Chat"
  Prof->>Prof: normalizeActor(name), validate
  Prof->>State: setRoom(handle)
  Prof->>Nav: navigate("/chat")
  Note over Prof,State: 以前のサーバ側ルーム作成呼び出しは削除
Loading
sequenceDiagram
  autonumber
  participant App as Application
  participant WS as WebSocket
  participant Srv as Server

  App->>App: detect mobile, read activeAccount
  App->>Srv: registerUser(activeAccount)
  App->>WS: connect()
  WS-->>App: events

  rect rgba(240,240,240,0.5)
    Note over App: 旧フロー(全アカウントTopUpの即時実行と5分間隔タイマー)は削除
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

ぴょんと跳ねてコードの森を駆け抜ける
鍵の落葉はさらりと掃き、道が軽くなる
タブもタイマーも静かにおやすみ
いまは部屋へ一直線、月のチャットへ
カリカリ…レビューの音、夜風とともに 🐇✨

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch codex/remove-e2ee-directory-and-imports

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

Type @coderabbitai help to get the list of available commands.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 2

Caution

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

⚠️ Outside diff range comments (1)
app/client/src/components/AddServerForm.tsx (1)

15-31: onAdd が例外を投げた場合にローディングが解除されず UI が固まる

await props.onAdd(...) が失敗すると後続の setIsLoading(false)・入力クリアが実行されず、ボタンが無期限で無効化されます。ユーザー体験に直結するため早めに修正してください。

   const handleSubmit = async (e: Event) => {
     e.preventDefault();
     setError("");
     if (!url()) {
       setError("サーバーURLを入力してください");
       return;
     }
     if (!password()) {
       setError("パスワードを入力してください");
       return;
     }
-    setIsLoading(true);
-    await props.onAdd(url().trim(), password());
-    setIsLoading(false);
-    setUrl("");
-    setPassword("");
+    setIsLoading(true);
+    try {
+      await props.onAdd(url().trim(), password());
+      // 成功時のみフィールドをクリア
+      setUrl("");
+      setPassword("");
+    } catch (err) {
+      // 失敗理由を表示(string 以外にも対応)
+      const msg = err instanceof Error ? err.message : "追加に失敗しました";
+      setError(msg);
+    } finally {
+      setIsLoading(false);
+    }
   };
🧹 Nitpick comments (5)
app/client/src/utils/firebase.ts (1)

10-10: Tauri 判定ロジックの一元化を提案

本ファイルでは __TAURI_IPC__ 存在チェックを用いていますが、app/client/src/utils/config.ts には isTauri() ヘルパーがあり、そちらは __TAURI__/__TAURI_INTERNALS__ も考慮しています。判定が分散すると条件不一致で挙動差が出る可能性があるため、共通ヘルパーに寄せることを推奨します。

適用例:

-import { apiFetch } from "./config.ts";
+import { apiFetch, isTauri as isTauriEnv } from "./config.ts";
 ...
-const isTauri = typeof window !== "undefined" && "__TAURI_IPC__" in window;
+const isTauri = isTauriEnv();

Also applies to: 16-16

app/api/routes/posts.ts (1)

231-233: objId の再代入は冗長—シンプル化可

objectId は直前で String((post as Record<string, unknown>)._id ?? "") によって定義済みです。ここでの || String((post...)) は実質的に同値なので簡略化できます。将来の読みやすさと意図の明確化のため、単純代入を提案します。

-const objId = objectId ||
-  String((post as Record<string, unknown>)._id ?? "");
+const objId = objectId;

補足: DB 実装上 _id が常に付与される前提であれば問題ありませんが、万一空文字になる可能性がある場合は、WebSocket通知前に if (!objId) return; のガード追加をご検討ください。前段の FASP 送信では truthy チェックがありますが、WS 側では現状無条件送信です。

app/client/src/components/Profile.tsx (1)

242-249: 微調整(任意):連続Signal更新のバッチング

UI再計算を減らすため、setRoomsetAppbatch でまとめると安定します(イベントハンドラ内なので差は小さいですが一応の最適化)。

例(外部参照用):

import { batch } from "solid-js";

const openChat = (): void => {
  const raw = username()?.trim();
  const user = account();
  if (!raw || !user) return;
  const handle = normalizeActor(raw);
  const normalized = handle.includes("@") ? handle : `${handle}@${getDomain()}`;
  batch(() => {
    setRoom(normalized);
    setApp("chat");
  });
};
app/client/src/components/microblog/api.ts (2)

374-374: キャッシュ書き込みは await して将来の非同期化に備える

現状は同期的な Map 書き込みのみですが、将来的に I/O 等へ拡張した際のフットガンを避けるため await を付与しておくのが安全です。

-    setCachedUserInfo(identifier, userInfo, accountId);
+    await setCachedUserInfo(identifier, userInfo, accountId);

併せて、型安全性を高めるなら JSON の型付けも推奨です(参考・任意):

-    const userInfo = await response.json();
+    const userInfo = (await response.json()) as UserInfo;

353-381: 同一 identifier の同時リクエスト重複を抑止する in-flight デデュープを検討

短時間に同一ユーザーを複数箇所で解決する場合、現状は都度 API が走ります。軽量な in-flight マップでのデデュープで負荷とレイテンシを下げられます。

実装イメージ(参考、抜粋・追加コード):

// ファイル先頭付近に追加
const inFlightUserFetches = new Map<string, Promise<UserInfo | null>>();

// fetchUserInfo の先頭でキー生成(上記の accountId:identifier 方式と同一に)
const key = (accountId ? `${accountId}:` : "") + identifier;
const existing = inFlightUserFetches.get(key);
if (existing) return await existing;

// 実リクエスト処理全体を Promise に包んで登録
const p = (async () => {
  const cached = await getCachedUserInfo(identifier, accountId);
  if (cached) return cached;

  const response = await apiFetch(`/api/users/${encodeURIComponent(identifier)}`);
  if (!response.ok) throw new Error("Failed to fetch user info");
  const userInfo = (await response.json()) as UserInfo;

  await setCachedUserInfo(identifier, userInfo, accountId);
  return userInfo;
})();

inFlightUserFetches.set(key, p);
try {
  return await p;
} finally {
  inFlightUserFetches.delete(key);
}
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 579444d and 8fcdb6f.

📒 Files selected for processing (17)
  • app/api/routes/posts.ts (1 hunks)
  • app/client/src/components/AddServerForm.tsx (2 hunks)
  • app/client/src/components/Application.tsx (1 hunks)
  • app/client/src/components/Profile.tsx (1 hunks)
  • app/client/src/components/Setting/index.tsx (0 hunks)
  • app/client/src/components/chat/ChatSettingsOverlay.tsx (0 hunks)
  • app/client/src/components/chat/ChatTitleBar.tsx (0 hunks)
  • app/client/src/components/e2ee/api.ts (0 hunks)
  • app/client/src/components/e2ee/binding.ts (0 hunks)
  • app/client/src/components/e2ee/mls_message.ts (0 hunks)
  • app/client/src/components/e2ee/mls_test.ts (0 hunks)
  • app/client/src/components/e2ee/mls_wrapper.ts (0 hunks)
  • app/client/src/components/e2ee/storage.ts (0 hunks)
  • app/client/src/components/e2ee/useMLS.ts (0 hunks)
  • app/client/src/components/microblog/api.ts (2 hunks)
  • app/client/src/utils/firebase.ts (1 hunks)
  • app/client/vite.config.mts (1 hunks)
💤 Files with no reviewable changes (10)
  • app/client/src/components/e2ee/useMLS.ts
  • app/client/src/components/chat/ChatTitleBar.tsx
  • app/client/src/components/e2ee/mls_test.ts
  • app/client/src/components/chat/ChatSettingsOverlay.tsx
  • app/client/src/components/e2ee/binding.ts
  • app/client/src/components/e2ee/mls_message.ts
  • app/client/src/components/e2ee/storage.ts
  • app/client/src/components/Setting/index.tsx
  • app/client/src/components/e2ee/mls_wrapper.ts
  • app/client/src/components/e2ee/api.ts
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: TypeScriptの型定義を活用する
エラーハンドリングを適切に実装する

Files:

  • app/client/src/utils/firebase.ts
  • app/api/routes/posts.ts
  • app/client/src/components/AddServerForm.tsx
  • app/client/src/components/Profile.tsx
  • app/client/src/components/Application.tsx
  • app/client/src/components/microblog/api.ts
app/api/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

環境変数は常に getEnv(c) を用いてコンテキストから取得する

Files:

  • app/api/routes/posts.ts
app/api/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Honoフレームワークのミドルウェアパターンに従う

Files:

  • app/api/routes/posts.ts
🧠 Learnings (1)
📚 Learning: 2025-08-13T10:14:15.274Z
Learnt from: CR
PR: takoserver/takos#0
File: CLAUDE.md:0-0
Timestamp: 2025-08-13T10:14:15.274Z
Learning: Applies to app/api/{activity_handlers.ts,utils/activitypub*.ts} : ActivityPubの仕様に準拠したJSON-LD形式を使用する

Applied to files:

  • app/client/src/components/microblog/api.ts
🧬 Code graph analysis (3)
app/client/src/utils/firebase.ts (1)
app/client/src/utils/config.ts (1)
  • isTauri (20-26)
app/api/routes/posts.ts (1)
app/api/routes/ws.ts (1)
  • broadcast (32-39)
app/client/src/components/microblog/api.ts (1)
app/api/services/user-info.ts (1)
  • UserInfo (6-12)
🔇 Additional comments (9)
app/client/vite.config.mts (1)

19-23: コメントの整形のみ—動作影響なし (LGTM)

説明・HMRの注意点も読みやすくなりました。機能差分は無く、そのままマージで問題ありません。

app/client/src/utils/firebase.ts (1)

57-62: クォートスタイル変更のみ—動作影響なし (LGTM)

動作に影響する変更はありません。

app/client/src/components/AddServerForm.tsx (1)

43-45: onInput の改行整形のみ—可読性向上 (LGTM)

イベント型注釈もそのままで問題ありません。

Also applies to: 54-56

app/client/src/components/Application.tsx (2)

1-1: 未使用だった import の整理—問題なし (LGTM)

onCleanup の削除に伴う差分で、実装上の影響はありません。


5-5: activeAccount ベースの登録のみへ簡素化—挙動確認のお願い

E2EE/トップアップ系の撤去によりアクティブアカウントの registerUser のみになりました。アカウント切り替え時に createEffect が確実に発火し、想定どおり再登録されるかを軽く手動確認しておいてください(HMR/再描画でも多重登録されない前提)。

app/client/src/components/Profile.tsx (2)

242-249: E2EE依存の除去に伴う openChat の同期化は方針どおりで良いです

サーバー呼び出しを外し、クライアント状態のみに集約した点は本PRの目的(E2EE撤去)と整合しています。


242-249: 要確認: ルーム遅延生成周りのUX/機能回帰

クライアント側には明示的なルーム事前生成ロジックが残っておらず、selectedRoomStatesetRoom の呼び出し箇所のみが見つかりました。以下の点を手動で動作検証してください。

• 呼び出し箇所

  • app/client/src/components/Profile.tsx(setRoom(handle))
  • app/client/src/components/home/NotificationsContent.tsx(setRoom(rid))
  • その他、Application.tsxheader.tsxrouter.ts 等で selectedRoomState を利用

• 古いルーム生成API呼び出しはなし

  • addRoomcreateRoomensureRoomopenRoom などの残存呼び出しは検出されず、クライアントからの明示的生成は行われていません。

• チャット送信前の存在前提コードなし

  • ChatSendForm.tsxprops.sendMessage() 呼び出し等、初回送信でもルーム存在を前提とする記述は見当たりません。

上記より、クライアント側のコードはサーバーの遅延ルーム生成前提に沿っているようです。
──
◎ 想定される挙動の手動確認

  1. 存在しないルームID(例: user@domainuser)でチャット画面を開き、画面描画がエラーなく完了するか
  2. 初回メッセージ送信時にサーバー側でルームが自動生成され、以降のメッセージ送受信が問題なく行えるか
  3. user@domainuser いずれも同一ユーザーとしてルーティングされるか

以上の動作確認をお願いします。

app/client/src/components/microblog/api.ts (2)

329-350: メモリ限定キャッシュへの移行方針は妥当(I/O 排除・単純化)

永続層を外したことで、I/O レイテンシと失敗モードが減り、フロント側の責務も明確になりました。この方向性自体は賛成です。


329-338: getCachedUserInfo の呼び出しとキャッシュ分離の手動確認をお願いします

ripgrep による自動検索では、fetchUserInfo / getCachedUserInfo の 2 引数呼び出しやアカウント識別子(activeAccount 等)の痕跡が検出できませんでした。自動検索結果は必ずしも呼び出し漏れの証明にはならないため、以下を手動でご確認ください。

  • 全ての getCachedUserInfo(identifier, accountId?) 呼び出し箇所で、第二引数として適切に accountId を渡しているか
  • 同様に、fetchUserInfo(identifier, accountId?) の呼び出しにも漏れがないか
  • 複数アカウント利用が想定されるコンポーネント(マルチテナント UI、アカウント切替機能など)で、キャッシュキーが accountId:identifier の形式で一貫して分離されているか
  • キャッシュの登録側(setCachedUserInfo や同等ロジック)にも同様のキー分離が反映されているか

上記の確認後、クロスアカウント汚染のリスクを避けるため、必要に応じてキー生成と呼び出し側を修正してください。

Comment on lines +340 to 350
export const setCachedUserInfo = (
identifier: string,
userInfo: UserInfo,
accountId?: string,
) => {
_accountId?: string,
): Promise<void> => {
userInfoCache.set(identifier, {
userInfo,
timestamp: Date.now(),
});
if (accountId) {
await saveCacheEntry(accountId, `userInfo:${identifier}`, userInfo);
}
return Promise.resolve();
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

setCachedUserInfo も accountId をキーに含めて対称性を担保する

getCachedUserInfo と対で、こちらもキー分離しないと期待通りにヒットしません。あわせて async 化して明示的 Promise.resolve() を除去できます。

-export const setCachedUserInfo = (
+export const setCachedUserInfo = async (
   identifier: string,
   userInfo: UserInfo,
-  _accountId?: string,
+  accountId?: string,
 ): Promise<void> => {
-  userInfoCache.set(identifier, {
+  const key = accountId ? `${accountId}:${identifier}` : identifier;
+  userInfoCache.set(key, {
     userInfo,
     timestamp: Date.now(),
   });
-  return Promise.resolve();
+  return;
 };
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const setCachedUserInfo = (
identifier: string,
userInfo: UserInfo,
accountId?: string,
) => {
_accountId?: string,
): Promise<void> => {
userInfoCache.set(identifier, {
userInfo,
timestamp: Date.now(),
});
if (accountId) {
await saveCacheEntry(accountId, `userInfo:${identifier}`, userInfo);
}
return Promise.resolve();
};
export const setCachedUserInfo = async (
identifier: string,
userInfo: UserInfo,
accountId?: string,
): Promise<void> => {
const key = accountId ? `${accountId}:${identifier}` : identifier;
userInfoCache.set(key, {
userInfo,
timestamp: Date.now(),
});
return;
};
🤖 Prompt for AI Agents
In app/client/src/components/microblog/api.ts around lines 340 to 350,
setCachedUserInfo currently only keys by identifier and returns
Promise.resolve(); update it to build the cache key the same way
getCachedUserInfo does (include accountId to separate caches, e.g. use
`${accountId ?? ''}:${identifier}` or the same helper used elsewhere), make the
function async and remove the explicit Promise.resolve(), and store the entry
under that composite key with userInfo and timestamp so lookups will hit
correctly.

Comment on lines +242 to 249
const openChat = () => {
const name = username();
const user = account();
if (!name || !user) return;
const handle = normalizeActor(name);
const me = `${user.userName}@${getDomain()}`;
await addRoom(
user.id,
{ id: handle, name: handle, members: [handle, me] },
{ from: me, content: "hi", to: [handle, me] },
);
setRoom(handle);
setApp("chat");
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

ローカル名のみのケースで '@Domain' が付与されず、ルームキーの一意性が崩れる可能性

現在の normalizeActor は 'http' からの変換以外では入力をそのまま返すため、alice のようなローカル名がそのまま setRoom("alice") に渡る可能性があります。アプリ内の他箇所が user@domain を前提にしていると、同名ユーザーの衝突やルーム解決ミスが発生します。入力を trim し、@ を含まない場合は getDomain() を補完して完全ハンドルに正規化するのが安全です。ついでに明示的な戻り値型を付けて型の意図も固定しておきましょう。

以下の差分を提案します(この範囲内のみで完結します):

-  const openChat = () => {
-    const name = username();
-    const user = account();
-    if (!name || !user) return;
-    const handle = normalizeActor(name);
-    setRoom(handle);
-    setApp("chat");
-  };
+  const openChat = (): void => {
+    const raw = username()?.trim();
+    const user = account();
+    if (!raw || !user) return;
+    const handle = normalizeActor(raw);
+    const normalized = handle.includes("@") ? handle : `${handle}@${getDomain()}`;
+    setRoom(normalized);
+    setApp("chat");
+  };

補足(代替案):

  • 上記の代わりに、normalizeActor(行229-240)側で「@ が無ければ @${getDomain()} を付与」する仕様へ寄せると呼び出し側がシンプルになります(どちらでも可)。

normalizeActorの実装を確認するため、以下のスクリプトを実行してください。


🏁 Script executed:

#!/bin/bash
# normalizeActorの定義箇所と実装内容を検索
rg -n "normalizeActor" -C3 --glob 'app/client/src/**/*.ts*'

Length of output: 1025


normalizeActor の完全な実装と、getDomain の定義箇所を確認するため、以下のスクリプトを実行してください。

#!/bin/bash
# Profile.tsx 内の normalizeActor 関数実装を表示
sed -n '229,247p' app/client/src/components/Profile.tsx

# getDomain 関数の定義箇所を検索
rg -n "getDomain" -C3 --glob 'app/client/src/**/*.ts*'

normalizeActor の実装と getDomain の定義を正確に把握するため、以下のスクリプトを実行してください。


🏁 Script executed:

#!/bin/bash
# Profile.tsx 内で normalizeActor の実装部分を表示
sed -n '229,240p' app/client/src/components/Profile.tsx

# getDomain 関数の定義箇所を検索
rg -n "getDomain" -C3 --glob 'app/client/src/**/*.ts*'

Length of output: 19007


openChat でローカル名のみの場合にドメインを補完し、一意のルームキーを確保しましょう

normalizeActor は HTTP URL 以外の入力をそのまま返すため、username()"alice" のようにドメインを含まない場合、setRoom("alice") となりうることを確認しました。アプリ内の他箇所では @${getDomain()} を付与した完全ハンドルを前提としているため、ここでも同様にドメインを補完しておくのが安全です。

対象箇所:

  • app/client/src/components/Profile.tsxopenChat 関数定義付近(およそ 242–249 行目)

提案差分:

-  const openChat = () => {
-    const name = username();
-    const user = account();
-    if (!name || !user) return;
-    const handle = normalizeActor(name);
-    setRoom(handle);
-    setApp("chat");
-  };
+  const openChat = (): void => {
+    const raw = username()?.trim();
+    const user = account();
+    if (!raw || !user) return;
+    const handle = normalizeActor(raw);
+    // ローカル名のみならドメインを補完
+    const normalized = handle.includes("@")
+      ? handle
+      : `${handle}@${getDomain()}`;
+    setRoom(normalized);
+    setApp("chat");
+  };

この修正で、ドメインを含まないローカル名でも常に user@domain 形式の一意ハンドルをルームキーに使えるようになります。

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const openChat = () => {
const name = username();
const user = account();
if (!name || !user) return;
const handle = normalizeActor(name);
const me = `${user.userName}@${getDomain()}`;
await addRoom(
user.id,
{ id: handle, name: handle, members: [handle, me] },
{ from: me, content: "hi", to: [handle, me] },
);
setRoom(handle);
setApp("chat");
};
const openChat = (): void => {
const raw = username()?.trim();
const user = account();
if (!raw || !user) return;
const handle = normalizeActor(raw);
// ローカル名のみならドメインを補完
const normalized = handle.includes("@")
? handle
: `${handle}@${getDomain()}`;
setRoom(normalized);
setApp("chat");
};
🤖 Prompt for AI Agents
In app/client/src/components/Profile.tsx around lines 242 to 249, openChat calls
normalizeActor and may get a local name like "alice" which lacks a domain;
update openChat to detect when the normalized handle is not an HTTP URL and does
not already contain '@', and then append "@${getDomain()}" (using the existing
getDomain() helper) so the room key is always in the "user@domain" form before
calling setRoom; ensure you import/get access to getDomain() if needed and leave
handles that are URLs or already include a domain unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant