Skip to content

feat: add model authenticity verification#2550

Open
Arlenman wants to merge 4 commits intofarion1231:mainfrom
Arlenman:feature/model-authenticity-verification
Open

feat: add model authenticity verification#2550
Arlenman wants to merge 4 commits intofarion1231:mainfrom
Arlenman:feature/model-authenticity-verification

Conversation

@Arlenman
Copy link
Copy Markdown

@Arlenman Arlenman commented May 3, 2026

Summary

  • Add a model authenticity verification page
  • Support OpenAI Chat, Anthropic Messages, and Gemini generateContent probes
  • Add confidence scoring, diagnostics, token/latency metrics, and local detection history
  • Add model list fetching, API key visibility/copy controls, notes, and JSON expand/
    collapse display

Verification

  • pnpm typecheck
  • cargo test -p cc-switch model_verify
  • locale JSON parse check

@Arlenman
Copy link
Copy Markdown
Author

Arlenman commented May 3, 2026

Hi maintainers, this PR adds a model authenticity verification page with protocol probes,
scoring, metrics, and local history. Could you please review it when available?

Copy link
Copy Markdown
Owner

@codex review
@claude review

@claude
Copy link
Copy Markdown

claude Bot commented May 3, 2026

Claude finished @farion1231's task in 2m 20s —— View job


Review of PR #2550 — Model Authenticity Verification

No blocking issues. A couple of i18n-localization nits where Chinese strings are hardcoded in user-visible UI paths.


🟡 Nit — Hardcoded Chinese fallback in MetricCard loading state

src/components/model-verify/ModelVerifyPage.tsx:631

<div className="mt-2 text-2xl font-semibold">
  {loading ? "等待中" : value}
</div>

While probes are running, every metric card shows the literal Chinese string 等待中 regardless of the active locale, including in en.json and ja.json. The rest of the page goes through t() (e.g. t("modelVerify.waiting") is already present in all three locale files), so this looks like an oversight.

Suggested fix: accept t (or a translated placeholder string) as a prop, or replace the literal with t("modelVerify.waiting"). Confidence: 95.

Fix this →


🟡 Nit — Hardcoded Chinese labels in pendingProbeGroups

src/components/model-verify/ModelVerifyPage.tsx:885-908

return [
  ["knowledgeQa", "知识问答校验"],
  ["modelFeatures", "型号特征校验"],
  ["protocolConsistency", "协议一致性"],
  ["responseStructure", "响应结构"],
].map(([id, label]) => ({ ... }));

The same group keys exist in all three locale files under modelVerify.groupDescriptions.*, but no matching groupLabels entries exist. While a verification is running, English/Japanese users will see the four Chinese group titles. Define translation keys for the labels (e.g. modelVerify.groupLabels.knowledgeQa) and resolve them via t(). Confidence: 90.


Other notes

  • score_result correctly handles the protocol-consistency-failure cap and tests cover the main scoring paths (src-tauri/src/services/model_verify.rs:882-945, plus six unit tests).
  • sanitize_excerpt is best-effort (it only redacts space-separated tokens with sk-/sk-ant-/AIza prefixes and bearer); since excerpts also cap at 500 chars and are local-only, this seems acceptable for the threat model.
  • validate_request parses the URL but does not restrict scheme. reqwest will still refuse file://, so no concrete attack scenario, but worth keeping in mind if the surface ever changes.
  • The new .github/workflows/manual-test-release.yml is gated on workflow_dispatch only and uses make_latest: false + prerelease: true, which is the right shape for an ad-hoc test build.

LGTM otherwise — I'll leave the merge decision to the maintainer.
• Branch: feature/model-authenticity-verification

Copy link
Copy Markdown

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

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

ℹ️ 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 +567 to +570
if response_type == Some("message") && !content.is_empty() {
(ProbeStatus::Passed, "Anthropic Messages 响应结构可解析".to_string(), excerpt)
} else {
(ProbeStatus::Warning, "Anthropic 响应结构不完整".to_string(), excerpt)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate Anthropic probes against expected outputs

This probe marks knowledgeQa, modelFeatures, and protocolConsistency as passed whenever the response has type message and non-empty text, regardless of whether the model actually returned 579, valid JSON, or OK for the prompt. That means incorrect Anthropic backends can still receive high confidence scores, which undermines the feature’s core authenticity signal.

Useful? React with 👍 / 👎.

Comment on lines +650 to +653
if has_candidates && !content.is_empty() {
(ProbeStatus::Passed, "Gemini generateContent 响应结构可解析".to_string(), excerpt)
} else {
(ProbeStatus::Warning, "Gemini 响应结构不完整".to_string(), excerpt)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Validate Gemini probes against expected outputs

The Gemini path uses the same pass condition for all main probes (has_candidates and non-empty content), so arithmetic/JSON/protocol probes can pass even when the returned content is wrong. In practice this can overstate confidence and hide protocol/model mismatches for Gemini endpoints.

Useful? React with 👍 / 👎.

Comment on lines +1000 to +1001
let latency_ms = probes.iter().filter_map(|probe| probe.latency_ms).max();
let latency_seconds = latency_ms.map(|value| value as f64 / 1000.0);
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 Compute total latency instead of max single-probe latency

Metrics currently set latency from the maximum probe duration, but the UI labels this as overall latency and uses it to derive tokens/sec. Using max rather than end-to-end (or summed) time underreports total runtime and inflates throughput numbers, producing misleading diagnostics.

Useful? React with 👍 / 👎.

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.

2 participants