Skip to content

fix(session): decode canonical detail route identities - #1388

Merged
ding113 merged 1 commit into
devfrom
fix/session-detail-encoding
Aug 3, 2026
Merged

fix(session): decode canonical detail route identities#1388
ding113 merged 1 commit into
devfrom
fix/session-detail-encoding

Conversation

@ding113

@ding113 ding113 commented Aug 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • 在 Session 详情页路由边界规范化 URL 编码后的 reserved canonical identity
  • 仅接受解码后以 pfx:sid: 开头的值,避免改变普通 physical Session ID
  • 修正组件测试的 stale mock 路径,并用生产中的 pfx%3A... 形态补充回归测试

Root Cause

目标 Session 已成功写入 message_requestusage_ledger,但详情页收到 URL 编码后的 pfx%3A... 并原样传给 REST client。REST client 再次执行 encodeURIComponent 后请求 %253A 键,无法命中数据库中的 pfx:... canonical identity,因此返回资源不存在。

Validation

  • bun run lint
  • bun run lint:fix
  • bun run typecheck
  • bun run build
  • bun run test (858 files passed, 8365 tests passed)
  • 聚焦 Session 详情组件回归测试
  • API client canonical/physical locator 编码契约测试

Greptile Summary

This PR normalizes URL-encoded reserved canonical session identities at the Session detail route boundary so the REST client does not double-encode them.

  • Decodes route parameters only when the decoded identity begins with pfx: or sid:, preserving ordinary physical Session IDs.
  • Updates the client-action mock path to the production API-client module.
  • Adds regression coverage for the encoded pfx%3A... route form.

Confidence Score: 5/5

The PR appears safe to merge, with the canonical route normalization matching the identity grammar and API-client encoding contract.

Reserved canonical identities use fixed pfx: or sid: prefixes and hexadecimal components, and the new normalization restores their canonical form before the REST client performs its required path-segment encoding without altering ordinary physical IDs.

Important Files Changed

Filename Overview
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx Adds guarded route-boundary decoding for canonical session identities while leaving ordinary physical IDs unchanged.
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx Corrects the mocked API-client module and verifies that an encoded canonical route identity is decoded before details are loaded.

Sequence Diagram

sequenceDiagram
  participant Route as Session detail route
  participant Client as SessionMessagesClient
  participant API as REST API client
  participant Server as Session details endpoint
  Route->>Client: pfx%3Ascope%3Afingerprint
  Client->>Client: decode reserved canonical identity
  Client->>API: pfx:scope:fingerprint
  API->>Server: encodeURIComponent(identity)
  Server-->>Client: Matching session details
Loading

Reviews (1): Last reviewed commit: "fix(session): decode canonical detail ro..." | Re-trigger Greptile

Context used:

@gemini-code-assist

Copy link
Copy Markdown
Contributor

Caution

The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased.

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

客户端现在会解码并校验 canonical Session ID 路由参数。测试覆盖解码后的 ID 传入 getSessionDetails,并更新相关 mock 与测试状态清理。

Changes

会话 ID 规范化

Layer / File(s) Summary
规范化会话路由参数
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx
新增 URL 解码和 pfx:sid: 前缀校验。解码失败或前缀不匹配时使用原始参数。
验证规范化后的详情加载
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
新增 URL 编码 canonical Session ID 的测试,并验证解码后的 ID 传入 getSessionDetails。测试使用可变路由参数,更新活动会话 API mock,并在测试后重置参数。

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: tesgth032

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed 标题准确概括了对 Session 详情路由中的 canonical identity 进行解码修复。
Description check ✅ Passed 描述明确说明了路由规范化、根因、测试变更和验证结果,与代码变更直接相关。
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/session-detail-encoding

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

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 631dfc18f5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +58 to +59
const decoded = decodeURIComponent(sessionId);
return decoded.startsWith("pfx:") || decoded.startsWith("sid:") ? decoded : sessionId;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve percent escapes in physical session IDs

When a valid client-supplied physical ID contains percent text that decodes to a reserved prefix, such as pfx%3Afoo, buildPublicSessionIdentity deliberately preserves it because the raw ID does not begin with pfx: or sid:. Next.js already percent-decodes dynamic route parameters (also documented in src/app/api/ip-geo/[ip]/route.ts:36), so a correctly encoded link for that ID supplies pfx%3Afoo here; this second decode changes it to pfx:foo, causing detail, request-list, export, and termination operations to target a different identity. Preserve the framework-decoded parameter rather than decoding it again.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx (1)

275-294: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

补充 sid: 和普通物理 Session ID 的回归用例。

当前用例只覆盖编码后的 pfx: 路由值。它没有覆盖 sid: 分支,也没有验证普通物理 Session ID 在规范化后保持不变。建议将该用例参数化,至少加入这两种输入。这样可以覆盖新增的接受前缀和原始值回退路径。

该建议基于本文件新增的前缀判断和回退逻辑。

🤖 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
`@src/app/`[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
around lines 275 - 294, 参数化“decodes an URL-encoded canonical Session ID before
loading details”测试,至少覆盖 URL 编码后的 sid: 值和普通物理 Session ID 输入;分别验证 sid:
前缀被正确规范化,以及普通物理 ID 规范化后保持不变,同时保留现有 pfx: 编码场景和预期的 getSessionDetailsMock 调用参数。
🤖 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.

Nitpick comments:
In
`@src/app/`[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx:
- Around line 275-294: 参数化“decodes an URL-encoded canonical Session ID before
loading details”测试,至少覆盖 URL 编码后的 sid: 值和普通物理 Session ID 输入;分别验证 sid:
前缀被正确规范化,以及普通物理 ID 规范化后保持不变,同时保留现有 pfx: 编码场景和预期的 getSessionDetailsMock 调用参数。

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b3595ef1-0a0b-437b-938c-e196f075ffdb

📥 Commits

Reviewing files that changed from the base of the PR and between 07fdc53 and 631dfc1.

📒 Files selected for processing (2)
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client-actions.test.tsx
  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

🧪 测试结果

测试类型 状态
代码质量
单元测试
集成测试
API 测试

总体结果: ✅ 所有测试通过

@github-actions github-actions Bot added the size/XS Extra Small PR (< 50 lines) label Aug 3, 2026
function normalizeCanonicalSessionRouteParam(sessionId: string): string {
try {
const decoded = decodeURIComponent(sessionId);
return decoded.startsWith("pfx:") || decoded.startsWith("sid:") ? decoded : sessionId;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[HIGH] [LOGIC-BUG] Double-decoding the route param can rewrite a valid physical Session ID

Why this is a problem: useParams() already exposes the decoded dynamic segment here; the repo relies on the same rule in src/app/api/ip-geo/[ip]/route.ts:36 ("Next.js already percent-decodes route params, so no manual decode."). Decoding a second time changes a raw physical ID like pfx%3Afoo into pfx:foo, which violates the identity contract in src/lib/request-identity.ts:45 where ordinary Session IDs are preserved unless they already start with pfx: or sid:. After that rewrite, detail loading, request lookup, exports, and termination all target the wrong identity.

Suggested fix:

const params = useParams<{ sessionId: string }>();
const sessionId = params.sessionId;

Then update the regression test to mock the runtime value that Next actually provides ("pfx:...") and add a case proving a physical ID such as "pfx%3Afoo" stays unchanged.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review Summary

I found one high-confidence correctness issue in the new route-param normalization. The client now double-decodes sessionId, which can rewrite valid raw physical IDs into reserved canonical identities and send detail, request, export, and terminate flows to the wrong session.

PR Size: XS

  • Lines changed: 39
  • Files changed: 2

Issues Found

Category Critical High Medium Low
Logic/Bugs 0 1 0 0
Security 0 0 0 0
Error Handling 0 0 0 0
Types 0 0 0 0
Comments/Docs 0 0 0 0
Tests 0 0 0 0
Simplification 0 0 0 0

Critical Issues (Must Fix)

  • None.

High Priority Issues (Should Fix)

  • src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx:59 double-decodes a route param that Next.js already decodes, so a raw physical ID such as pfx%3Afoo is rewritten to pfx:foo and subsequent detail/request/export/terminate calls can target the wrong identity.

Review Coverage

  • Logic and correctness
  • Security (OWASP Top 10)
  • Error handling
  • Type safety
  • Documentation accuracy
  • Test coverage
  • Code clarity

Automated review by Codex AI

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

  • Reviewed PR #1388 from the actual checkout state (pull/1388/merge), not the unrelated latest open PR.
  • Applied the size label size/XS.
  • Posted 1 inline review comment on src/app/[locale]/dashboard/sessions/[sessionId]/messages/_components/session-messages-client.tsx:59.
  • Submitted the required summary review on the PR.
  • The validated finding is a high-confidence logic bug: the new helper double-decodes sessionId, which can rewrite valid raw physical IDs like pfx%3Afoo into reserved canonical identities and send detail/request/export/terminate flows to the wrong session.

@ding113
ding113 merged commit b82ca39 into dev Aug 3, 2026
20 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Claude Code Hub Roadmap Aug 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/XS Extra Small PR (< 50 lines)

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant