テレメトリ送信をGraphQLに刷新(3種トークン認証・sessionId・インタラクションイベント)#29
Conversation
docker-compose の grafana サービス・ボリューム、プロビジョニング設定、 .env.example の GF_SECURITY_ADMIN_PASSWORD を削除。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- sendLogEvent / sendLocation Mutation を追加し、REST送信系 (/api/location, /api/log) と openapi.yaml を廃止 - 認証トークンを役割ごとに分離: - THQ_OBSERVER_AUTH_TOKEN: WebSocket購読のみ - THQ_EVENTS_AUTH_TOKEN: ログイベント送信のみ - THQ_TELEMETRY_AUTH_TOKEN: ログイベント+位置情報送信 - THQ_WS_AUTH_TOKEN / THQ_WS_AUTH_REQUIRED は THQ_AUTH_REQUIRED と上記3変数に置き換え Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- docs/react-tanstack-query.md: GraphQL でのイベント送信・集計取得 - docs/react-websocket-observer.md: WebSocket での観測(購読) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- sendLogEvent / sendLocation の入力から id を削除し、 クライアント生成の一意な文字列 sessionId を必須化 - イベントIDは常にサーバー側でUUIDを採番 - session_id を WS 配信メッセージと DB 両テーブルに追加 (既存テーブルにはべき等な ADD COLUMN で対応) - あわせて sendLogEvent の device を匿名送信のため任意化 (log_events.device を NULL 許容に変更) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 任意のイベント名(eventName)でユーザー行動を記録する Mutation - 認証・入力仕様はログイベントを踏襲 (sessionId必須・device任意・観測用以外のトークンで送信可) - WS には type: "interaction" として配信 - interaction_events テーブルに永続化(event_name / session_id に索引) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- Record<string, string | number | boolean | null> 相当の フラットなオブジェクトのみ受理するカスタムスカラー Properties を追加 (ネストしたオブジェクト・配列は型レベルで拒否) - WS 配信メッセージに properties を含め、 interaction_events に JSONB カラムとして永続化 - sqlx に json feature を追加 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- async-graphqlのデフォルト(SCREAMING_SNAKE_CASE)を rename_items = "lowercase" で上書き - platform: ios / channel: production など全enumが対象 (type, level, state, batteryState, bucketSize も統一) - WS配信・DB表現(小文字)とGraphQL表記が一致するように BREAKING CHANGE: 旧来の大文字enum値(IOS, PRODUCTION等)は拒否される Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Warning Review limit reachedYou’ve reached a temporary PR review limit under our Fair Usage Limits Policy. Next review available in: 59 minutes Your organization has reached its usage spending cap. Adjust your spending cap in the billing tab. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (7)
📝 WalkthroughWalkthroughREST API中心の構成を、役割別認証を備えたGraphQLミューテーションとTelemetry WebSocketへ移行しました。イベントモデル、PostgreSQL永続化、サーバー認証、Compose設定、React利用ドキュメントを更新しています。 ChangesGraphQL・Telemetry移行
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant GraphQL
participant MutationRoot
participant TelemetryHub
participant PostgreSQL
Client->>GraphQL: Authorization付きmutation
GraphQL->>MutationRoot: 認証権限付きで実行
MutationRoot->>TelemetryHub: telemetryイベントを配信
MutationRoot->>PostgreSQL: イベントを保存
MutationRoot-->>Client: 結果とwarning
Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
@coderabbitai review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 5
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docker-compose.yml`:
- Around line 9-12: THQ_AUTH_REQUIRED=false
の場合でも3つの認証トークンが必須になっているため、docker-compose.yml の
THQ_OBSERVER_AUTH_TOKEN、THQ_EVENTS_AUTH_TOKEN、THQ_TELEMETRY_AUTH_TOKEN
を認証設定に応じて任意扱いに変更してください。Compose
の変数展開だけで条件分岐できない場合は、認証無効時にダミー値を使用する構成または必要な設定方法をドキュメント化してください。
In `@docs/react-tanstack-query.md`:
- Around line 404-421: Update the geolocation effect to avoid stale values by
extracting the stable mutation function from sendLocation and adding the
referenced sessionId and mutation function to the useEffect dependency array;
retain the existing watchPosition setup and cleanup via clearWatch.
In `@docs/react-websocket-observer.md`:
- Around line 201-230:
接続直後の切断で再試行上限が無効化されないよう、WebSocketのonopenでretriesを無条件に0へ戻さないでください。一定時間安定して接続できた場合にのみリセットする仕組み、または時間窓内の累積試行数で制限する仕組みを、onopen・onclose・connectの再接続ロジックに実装してください。
In `@README.md`:
- Around line 80-82: Update the README authentication environment-variable table
entries for events_auth_token and telemetry_auth_token to explicitly mention
permission to send interaction events via sendInteractionEvent, while preserving
their existing sendLogEvent and sendLocation descriptions.
In `@src/server.rs`:
- Line 108: Update the /graphql route in the server router to avoid exposing
graphql_playground without authentication: disable the GET Playground endpoint
in production or protect it with the existing authentication and environment
checks, while keeping POST graphql_handler behavior unchanged.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: bcac062f-59e1-4715-bb6e-618d7de1cdb4
📒 Files selected for processing (15)
.env.exampleCargo.tomlREADME.mddocker-compose.ymldocs/react-tanstack-query.mddocs/react-websocket-observer.mdgrafana/provisioning/datasources/postgres.ymlopenapi.yamlsrc/config.rssrc/domain.rssrc/graphql.rssrc/main.rssrc/segment.rssrc/server.rssrc/storage.rs
💤 Files with no reviewable changes (2)
- openapi.yaml
- grafana/provisioning/datasources/postgres.yml
| THQ_OBSERVER_AUTH_TOKEN: ${THQ_OBSERVER_AUTH_TOKEN:?set in .env or shell} | ||
| THQ_EVENTS_AUTH_TOKEN: ${THQ_EVENTS_AUTH_TOKEN:?set in .env or shell} | ||
| THQ_TELEMETRY_AUTH_TOKEN: ${THQ_TELEMETRY_AUTH_TOKEN:?set in .env or shell} | ||
| THQ_AUTH_REQUIRED: ${THQ_AUTH_REQUIRED:-true} |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
THQ_AUTH_REQUIRED=false でもトークンを必須にしないでください。
Compose の ${VAR:?…} は THQ_AUTH_REQUIRED の値に関係なく評価されるため、認証を無効化したローカル環境でも3トークンが未設定だと起動できません。トークンを条件付きで任意にするか、認証無効時もダミー値が必要であることをドキュメント化してください。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docker-compose.yml` around lines 9 - 12, THQ_AUTH_REQUIRED=false
の場合でも3つの認証トークンが必須になっているため、docker-compose.yml の
THQ_OBSERVER_AUTH_TOKEN、THQ_EVENTS_AUTH_TOKEN、THQ_TELEMETRY_AUTH_TOKEN
を認証設定に応じて任意扱いに変更してください。Compose
の変数展開だけで条件分岐できない場合は、認証無効時にダミー値を使用する構成または必要な設定方法をドキュメント化してください。
フロント(観測用トークンのみ)はDBへ直接アクセスできないため、 バッファ外の履歴取得先としてDBを案内するのは誤り。認証不要の GraphQL Query accuracyByLine(集計)への案内のみ残す。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- GET /graphql の Playground を削除し POST /graphql のみに - 認証の有効/無効トグル THQ_AUTH_REQUIRED を廃止。認証は常に必須とし、 トークンが1つも設定されていない場合は起動時にエラーで終了する - 関連する設定(README / docker-compose / .env.example)とドキュメントを更新 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
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 (2)
README.md (1)
7-11: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
sendInteractionEventを機能・権限要約にも記載してください。Line 7 と Line 11 はログのみを対象にしており、後段の認証表・API仕様にあるinteractionイベントと矛盾します。
修正案
-- **WebSocket** — Real-time broadcast of location updates and log events +- **WebSocket** — Real-time broadcast of location updates, log events, and interaction events ... -- **Scoped authentication** — Three shared secrets: observer (WebSocket only), events (log submission only), telemetry (log + location submission) +- **Scoped authentication** — Three shared secrets: observer (WebSocket only), events (log + interaction submission), telemetry (log + interaction + location submission)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@README.md` around lines 7 - 11, Update the README feature and authentication summaries to explicitly include interaction events alongside log events, particularly in the event ingestion and scoped-authentication descriptions, so they match the documented sendInteractionEvent API and permissions.docs/react-websocket-observer.md (1)
13-15: 🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift公開ブラウザに観測用トークンを埋め込む前提は避けてください。 これは共有秘密なので、保持者は誰でも WebSocket に接続して
location_update/log/interactionを受信できます。公開表示が必要なら BFF/認可プロキシで利用者ごとの認可と必要イベントの絞り込みを行い、ブラウザにはトークンを渡さない構成にしてください。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@docs/react-websocket-observer.md` around lines 13 - 15, Update the WebSocket observer documentation to prohibit embedding observation tokens in public browser builds. State that public access must go through a BFF or authorization proxy that applies per-user authorization and filters events, without exposing the token to browsers; retain rotation guidance only as a fallback for non-public deployments.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/config.rs`:
- Around line 103-109: 認証トークンの存在判定が空文字や空白のみの値を許可しています。`any_token` の判定を各トークンへ
`as_deref().is_some_and(|token| !token.trim().is_empty())`
相当のチェックを適用する形に変更し、CLI・環境変数・TOML の `Some("")`
および空白のみを拒否してください。空値のみのケースを検証するテストも追加してください。
---
Outside diff comments:
In `@docs/react-websocket-observer.md`:
- Around line 13-15: Update the WebSocket observer documentation to prohibit
embedding observation tokens in public browser builds. State that public access
must go through a BFF or authorization proxy that applies per-user authorization
and filters events, without exposing the token to browsers; retain rotation
guidance only as a fallback for non-public deployments.
In `@README.md`:
- Around line 7-11: Update the README feature and authentication summaries to
explicitly include interaction events alongside log events, particularly in the
event ingestion and scoped-authentication descriptions, so they match the
documented sendInteractionEvent API and permissions.
🪄 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: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: e085c180-daa4-451d-96f1-8110750ec10a
📒 Files selected for processing (8)
.env.exampleREADME.mddocker-compose.ymldocs/react-tanstack-query.mddocs/react-websocket-observer.mdsrc/config.rssrc/main.rssrc/server.rs
💤 Files with no reviewable changes (3)
- src/main.rs
- .env.example
- docker-compose.yml
onopen で無条件に retries を 0 に戻すと、接続直後に切断される状態で MAX_RETRIES が実質無効化され、約1秒間隔の無限再接続(接続ストーム)に 陥る。一定時間(STABLE_CONNECTION_MS)安定して接続できた場合にのみ リセットし、安定前に切断されたらリセット予約を取り消すよう修正。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- config.rs: clap は空の環境変数を Some("") として渡すため、空文字・
空白のみのトークンを未設定として正規化。空トークンのまま起動して
認証不能/空トークン認証が通る設定を弾く。検証テストを追加
- README: 環境変数表の events/telemetry トークン説明に
sendInteractionEvent の権限を明記(権限表との齟齬を解消)
CodeRabbit のレビュー指摘(PR #29)に対応。
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CodeRabbit Autofix 適用CodeRabbit のレビュー指摘 2 件に対応しました。 修正ファイル:
コミット: なお |
|
@coderabbitai review |
✅ Action performedReview finished.
|
|
@coderabbitai review |
✅ Action performedReview finished.
|
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Fixes Applied SuccessfullyFixed 1 file(s) based on 1 CodeRabbit feedback item(s). Files modified:
Commit: The latest autofix changes are on the |
sendLogEvent / sendInteractionEvent / sendLocation に対応する logEvents / interactionEvents / locations クエリを実装。 永続化済みイベントを新しい順に返し、sessionId / device / from / to / limit の共通フィルタと各クエリ固有のフィルタを受け付ける。 生データを公開しない方針を維持するため、履歴クエリは観測用トークン (Authorization: Bearer) を必須とし、RequestAuth に can_read_events スコープを追加。集計のみの accuracyByLine は従来どおり認証不要。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011En6FDKKTV7dqYKh367PT1
|
@coderabbitai review |
✅ Action performedReview finished.
|
概要
イベント送信系を REST から GraphQL Mutation に全面移行し、認証・入力スキーマ・イベント種別を刷新します。
変更内容
イベント送信の GraphQL 移行 (7318bb8)
sendLogEvent/sendLocationMutation を追加し、REST 送信系(POST /api/location,POST /api/log)と openapi.yaml を廃止THQ_OBSERVER_AUTH_TOKEN— WebSocket 購読のみTHQ_EVENTS_AUTH_TOKEN— ログ・インタラクションイベント送信THQ_TELEMETRY_AUTH_TOKEN— 上記+位置情報送信THQ_WS_AUTH_TOKEN/THQ_WS_AUTH_REQUIREDは上記3変数に置き換え(要 .env 更新)入力スキーマの刷新 (3857240, 88ad784)
idを廃止し、クライアント生成の一意な文字列sessionIdを必須化(イベント ID は常にサーバー採番)sendLogEventのdeviceを匿名送信のため任意化platform: ios,channel: productionなど)インタラクションイベント (abcb597, ee27862)
sendInteractionEventを追加(例:app_launch,tab_change,tts_success)appVersion/platform/channelをログ・インタラクション両イベントの必須フィールドにproperties(Record<string, string | number | boolean | null>相当のフラットなオブジェクトのみ受理)を追加し、JSONB で永続化認証の常時必須化と Playground 廃止 (053cd4b)
THQ_AUTH_REQUIREDを廃止。認証は常に必須で、トークンが1つも設定されていない場合は起動時にエラーで終了するGET /graphql)を廃止し、GraphQL はPOST /graphqlのみにその他
docs/に追加 (80f79e0)検証
破壊的変更
THQ_AUTH_REQUIREDの廃止(認証は常時必須・無効化不可。トークン未設定では起動失敗)GET /graphql)の廃止id廃止・sessionId/appVersion/platform/channel必須化🤖 Generated with Claude Code
Summary by CodeRabbit