Skip to content

fix: hide api key when provider is excluded from export#423

Merged
ymkiux merged 5 commits intomainfrom
fix/hide-api-key-for-excluded-provider
Mar 17, 2026
Merged

fix: hide api key when provider is excluded from export#423
ymkiux merged 5 commits intomainfrom
fix/hide-api-key-for-excluded-provider

Conversation

@awsl233777
Copy link
Collaborator

@awsl233777 awsl233777 commented Mar 17, 2026

Summary

When a custom provider has 从导出与备份中排除 / Exclude from export enabled, editing that provider should not still display the editable API key field.

This change hides the API Key (leave empty to keep current) field in the custom provider edit flow when excludeFromExport is enabled for the provider.

Why

If a provider is explicitly marked to be excluded from export/backup, continuing to expose the editable API key field in the edit page weakens the intent of that setting and creates a confusing UX.

Changes

  • add a shouldShowApiKeyField guard in ProviderEditFlow
  • hide the custom provider API key edit input when provider.excludeFromExport is true
  • keep the rest of the edit form unchanged

Testing

  • pnpm -C web exec tsc --noEmit

Summary by CodeRabbit

发布说明

  • 新功能

    • 新增“模型映射”部分,支持添加、编辑和删除映射配置。
  • 用户界面改进

    • 优化“错误冷却”与“导出排除”项的布局与说明位置。
    • 根据“导出排除”设置条件性显示 API 密钥字段,隐藏时显示提示说明并保留密钥显示切换控制。
  • 文案/本地化

    • 添加用于提示隐藏 API 密钥的本地化字符串(中/英)。

@awsl233777
Copy link
Collaborator Author

测试结论

  • pnpm -C web exec tsc --noEmit

改动说明

  • 当 provider 开启 从导出与备份中排除 时,编辑页不再显示 API 密钥(留空保持当前值) 输入框
  • 改动范围仅限:web/src/pages/providers/components/provider-edit-flow.tsx

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Warning

Rate limit exceeded

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

⌛ 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 481993f0-4d95-48b9-9b4f-ab9fa08f2485

📥 Commits

Reviewing files that changed from the base of the PR and between 79f25df and 9974ae0.

📒 Files selected for processing (3)
  • web/src/locales/en.json
  • web/src/locales/zh.json
  • web/src/pages/providers/components/provider-edit-flow.tsx
📝 Walkthrough

Walkthrough

重组自定义配置步骤的若干 UI 布局(错误冷却、排除导出),新增“模型映射”可增删条目,并在提供者编辑流程中基于 excludeFromExport 条件隐藏/展示 API 密钥编辑区域;同时添加相应的本地化字符串。

Changes

Cohort / File(s) Summary
自定义配置 UI
web/src/pages/providers/components/custom-config-step.tsx
调整“错误冷却”与“排除导出”块的布局(将描述置于标题下并将开关置右),保持表单更新逻辑;新增“模型映射”区域,包含添加、编辑(pattern 与目标模型)、删除及对应状态更新逻辑。
编辑流程 — 条件渲染 API 密钥
web/src/pages/providers/components/provider-edit-flow.tsx
引入 shouldShowApiKeyField(基于 excludeFromExport),将 API 密钥输入改为条件渲染;在隐藏时显示不可编辑的占位说明,并保留显示/隐藏切换行为。
本地化字符串
web/src/locales/en.json, web/src/locales/zh.json
新增 provider.apiKeyHiddenForExcluded 文案(英文与中文),用于在 API 密钥被隐藏时向用户说明原因与操作指引。

Sequence Diagram(s)

(无)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested reviewers

  • ymkiux
  • Bowl42

诗篇

🐰 新界面轻轻跳,
映射行列添新条,
开关右移更精神,
密钥隐现随标识,
兔子拍掌又摇尾。

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed 标题准确地总结了主要变更:当提供商被排除从导出时隐藏 API 密钥,这正是本 PR 的核心目标。

✏️ 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 fix/hide-api-key-for-excluded-provider
📝 Coding Plan
  • Generate coding plan for human review comments

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 and usage tips.

@awsl233777
Copy link
Collaborator Author

更新说明

已按反馈调整:从导出与备份中排除 不再放在 错误冷冻 分组里,而是改成创建页上的同级独立区块显示。

本次改动

  • CustomConfigStep 中的 excludeFromExport 开关从 errorCooldownTitle 分组内移出
  • 改为与 错误冷冻 同级的独立 section 展示
  • 改动范围仍限制在:web/src/pages/providers/components/custom-config-step.tsx

测试结论

  • pnpm -C web exec tsc --noEmit

Copy link

@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.

Caution

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

⚠️ Outside diff range comments (1)
web/src/pages/providers/components/provider-edit-flow.tsx (1)

637-689: ⚠️ Potential issue | 🟡 Minor

隐藏 API Key 后应同步调整网格列数,避免空白列。

Line [637] 仍固定为 md:grid-cols-2。当 Line [662] 条件为 false 时,右侧会留下空列,编辑页出现明显留白。建议按 shouldShowApiKeyField 动态切换列数。

可选修复示例
-              <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
+              <div
+                className={`grid grid-cols-1 gap-6 ${
+                  shouldShowApiKeyField ? 'md:grid-cols-2' : ''
+                }`}
+              >
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/providers/components/provider-edit-flow.tsx` around lines 637 -
689, The two-column grid is fixed to md:grid-cols-2 causing an empty column when
shouldShowApiKeyField is false; update the container around the inputs (the div
with className "grid grid-cols-1 md:grid-cols-2 gap-6") to compute the md column
count from shouldShowApiKeyField (e.g. switch between md:grid-cols-2 and
md:grid-cols-1 or set a cols variable) so the layout collapses to a single
column when shouldShowApiKeyField is false; ensure you only change the className
logic (not the Input components) and reference shouldShowApiKeyField in that
computation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@web/src/pages/providers/components/provider-edit-flow.tsx`:
- Around line 637-689: The two-column grid is fixed to md:grid-cols-2 causing an
empty column when shouldShowApiKeyField is false; update the container around
the inputs (the div with className "grid grid-cols-1 md:grid-cols-2 gap-6") to
compute the md column count from shouldShowApiKeyField (e.g. switch between
md:grid-cols-2 and md:grid-cols-1 or set a cols variable) so the layout
collapses to a single column when shouldShowApiKeyField is false; ensure you
only change the className logic (not the Input components) and reference
shouldShowApiKeyField in that computation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1e80531f-86e2-42a9-b571-7a0439f876cb

📥 Commits

Reviewing files that changed from the base of the PR and between a2242ad and fe2d711.

📒 Files selected for processing (2)
  • web/src/pages/providers/components/custom-config-step.tsx
  • web/src/pages/providers/components/provider-edit-flow.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: e2e
  • GitHub Check: playwright
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.
🔇 Additional comments (2)
web/src/pages/providers/components/provider-edit-flow.tsx (1)

310-310: shouldShowApiKeyField 守卫实现清晰且符合目标。

这里用 !provider.excludeFromExport 作为单一判断源,逻辑直观,且与“排除导出时隐藏 API Key”目标一致。

web/src/pages/providers/components/custom-config-step.tsx (1)

228-242: 错误冷却与导出排除开关的拆分实现正确。

两个开关现在是独立配置区块,语义更清楚,且 onCheckedChange 仍分别写回对应字段,未引入提交流程回归。

Also applies to: 244-259

@ymkiux
Copy link
Contributor

ymkiux commented Mar 17, 2026

@coderabbitai re-review !Stop making breaking changes, do a proper review!

@awsl233777
Copy link
Collaborator Author

继续修复

已按评论建议继续调整编辑页布局:当 shouldShowApiKeyFieldfalse 时,编辑页基础信息区域不再固定为两列,避免右侧出现空白列。

本次改动

  • web/src/pages/providers/components/provider-edit-flow.tsx
    • grid grid-cols-1 md:grid-cols-2 gap-6 改为根据 shouldShowApiKeyField 动态切换列数
    • 隐藏 API Key 时自动收缩为单列布局

测试结论

  • pnpm -C web exec tsc --noEmit

@coderabbitai re-review

!Stop making breaking changes, do a proper review!

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd "provider-edit-flow.tsx" --exec cat {}
echo "---FILE_BOUNDARY---"
fd "custom-config-step.tsx" --exec cat {}

Length of output: 42188


@ymkiux Here is a thorough re-review focused on correctness, regressions, and breaking changes.


provider-edit-flow.tsx

🔴 Breaking Change: API key can never be updated for excluded providers

const shouldShowApiKeyField = !provider.excludeFromExport;

When provider.excludeFromExport is true, the API key input is permanently hidden from the edit form. This means once a provider is marked as "excluded from export," its API key can never be rotated or updated through the UI. Previously, all custom providers allowed API key editing unconditionally. This is a behavioral regression.

There is also no visual cue to the user explaining why the field is absent — they will simply see the base URL input expanded to full width with no explanation.

Suggested fix: Either show a placeholder/notice instead of silently removing the field, or allow editing the key but simply exclude it from the export payload:

{shouldShowApiKeyField ? (
  <div>
    {/* existing API key input */}
  </div>
) : (
  <div className="p-3 bg-muted/50 border border-border rounded-lg text-xs text-muted-foreground flex items-center gap-2">
    <Key size={13} />
    <span>{t('provider.apiKeyHiddenForExcluded')}</span>
  </div>
)}

🟡 Semantic mismatch: export exclusion ≠ edit permission

excludeFromExport signals "do not include this provider in export/backup." Hiding the API key field conflates export safety with edit permissions. These are orthogonal concerns. A user may legitimately want to exclude a provider from export and still be able to rotate its key.

✅ Save/clone: API key is correctly preserved

When the field is hidden, formData.apiKey is initialized from provider.config?.custom?.apiKey || '', and the save path uses formData.apiKey || provider.config?.custom?.apiKey || '' — so the existing key is preserved on save and clone. No data loss occurs.

✅ Layout

The grid class correctly collapses: ${shouldShowApiKeyField ? 'md:grid-cols-2' : ''} — base URL expands to full width when the key field is absent.


custom-config-step.tsx

excludeFromExport section separation

The refactoring correctly splits excludeFromExport into its own independent section, sibling to errorCooldownTitle. The switch binding (updateFormData({ excludeFromExport: checked })) and save path (excludeFromExport: !!formData.excludeFromExport) are both correct. No regressions here.

🟡 createModelMapping call is missing fields

When saving template model mappings during provider creation:

await createModelMapping.mutateAsync({
  scope: 'provider',
  providerID: provider.id,
  pattern: mapping.pattern,
  target: mapping.target,
});

The equivalent call in ProviderModelMappings provides providerType, priority, and isEnabled. While TypeScript accepts this (fields are likely optional), omitting isEnabled means newly created template mappings may default to disabled depending on the backend default — worth verifying.


Summary table:

Location Severity Issue
provider-edit-flow.tsx 🔴 Breaking API key permanently uneditable for excluded providers; no user feedback
provider-edit-flow.tsx 🟡 Design excludeFromExport flag conflated with edit permission
custom-config-step.tsx excludeFromExport section separation is correct
custom-config-step.tsx 🟡 Minor createModelMapping omits providerType, priority, isEnabled

🧠 Learnings used
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.
✅ Actions performed

Full review triggered.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd "provider-edit-flow.tsx" --exec cat {}
echo "---FILE_BOUNDARY---"
fd "custom-config-step.tsx" --exec cat {}

Length of output: 42188


@awsl233777 The layout fix (dynamic grid columns) is confirmed correct — base URL expands to full width when the key field is hidden, no empty column. That part is good.

However, the 🔴 breaking change I raised previously is still present and there is actually a compounding issue now visible in the code:


🔴 Still Breaking: API key permanently inaccessible for excluded providers

Issue 1 — No user explanation. When provider.excludeFromExport is true, the API key field disappears silently. There is no label, notice, or placeholder telling the user why the field is absent. From the user's perspective, the field simply vanished.

Issue 2 — excludeFromExport cannot be toggled in the edit form. In handleSave:

excludeFromExport: !!provider.excludeFromExport,  // ← always from the original prop

EditFormData doesn't include excludeFromExport, and there's no toggle in the edit UI for it. So once a provider is created with excludeFromExport: true, there is no way through the edit form to set it back to false — meaning the API key is permanently locked out from editing, forever.

A minimal fix would be to add a readonly notice in place of the hidden field, e.g.:

{shouldShowApiKeyField ? (
  <div>
    {/* existing API key input */}
  </div>
) : (
  <p className="text-xs text-muted-foreground p-3 border border-border rounded-lg bg-muted/50">
    {t('provider.apiKeyHiddenForExcluded')}
  </p>
)}

Or alternatively, surface the excludeFromExport toggle in the edit form so users can reverse it.


🟡 Still Present: createModelMapping in custom-config-step.tsx omits fields

await createModelMapping.mutateAsync({
  scope: 'provider',
  providerID: provider.id,
  pattern: mapping.pattern,
  target: mapping.target,
  // missing: providerType, priority, isEnabled
});

Compare with the equivalent call in ProviderModelMappings which passes providerType: 'custom', priority, and isEnabled: true. Omitting isEnabled risks template mappings being created as disabled by default depending on the backend.


✅ Confirmed Correct

Item Status
Dynamic grid cols (layout fix)
excludeFromExport section separated in custom-config-step.tsx
Existing API key preserved on save/clone
excludeFromExport switch binding in custom-config-step.tsx

🧠 Learnings used
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.

Copy link

@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

🧹 Nitpick comments (1)
web/src/pages/providers/components/custom-config-step.tsx (1)

244-259: UI 不一致:排除导出部分缺少内部标签

与 Error Cooldown 部分相比,该部分的卡片内部缺少标签/标题。Error Cooldown 在卡片内有 text-sm font-medium 的标签和 text-xs 的描述,而此处只有描述段落。

♻️ 建议添加内部标签以保持一致性
           <div className="flex items-center justify-between p-4 bg-card border border-border rounded-xl">
             <div className="pr-4">
+              <div className="text-sm font-medium text-foreground">
+                {t('provider.excludeFromExport')}
+              </div>
               <p className="text-xs text-muted-foreground mt-1">
                 {t('provider.excludeFromExportDesc')}
               </p>
             </div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@web/src/pages/providers/components/custom-config-step.tsx` around lines 244 -
259, The card for the exclude-from-export toggle is missing the internal
label/title that Error Cooldown uses; inside the card wrapping the Switch (the
same div containing the description and Switch), add a label element (matching
the style used for Error Cooldown, e.g., class "text-sm font-medium") that
renders the title text via t('provider.excludeFromExport') or a shorter label,
keep the existing description paragraph using
t('provider.excludeFromExportDesc'), and ensure the Switch still binds to
formData.excludeFromExport and updateFormData({ excludeFromExport: checked }) so
the visual structure matches Error Cooldown.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/pages/providers/components/provider-edit-flow.tsx`:
- Line 310: The change hides the API Key field when provider.excludeFromExport
is true, which unnecessarily prevents key rotation; update the rendering logic
in ProviderEditFlow (where shouldShowApiKeyField is computed) so that
excludeFromExport no longer fully hides the API Key input—instead either (A)
always render the API Key input and keep it editable while still excluding the
provider from export, or (B) render the API Key field as readOnly/disabled and
display a small explanatory hint when provider.excludeFromExport is true; adjust
the code that uses shouldShowApiKeyField (and any conditional JSX around the API
Key input) to implement one of these behaviors and ensure the UI shows a clear
message tied to provider.excludeFromExport.

---

Nitpick comments:
In `@web/src/pages/providers/components/custom-config-step.tsx`:
- Around line 244-259: The card for the exclude-from-export toggle is missing
the internal label/title that Error Cooldown uses; inside the card wrapping the
Switch (the same div containing the description and Switch), add a label element
(matching the style used for Error Cooldown, e.g., class "text-sm font-medium")
that renders the title text via t('provider.excludeFromExport') or a shorter
label, keep the existing description paragraph using
t('provider.excludeFromExportDesc'), and ensure the Switch still binds to
formData.excludeFromExport and updateFormData({ excludeFromExport: checked }) so
the visual structure matches Error Cooldown.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 665b87f3-36e6-4ee5-aef8-8b6faf463061

📥 Commits

Reviewing files that changed from the base of the PR and between a2242ad and 5b18a0d.

📒 Files selected for processing (2)
  • web/src/pages/providers/components/custom-config-step.tsx
  • web/src/pages/providers/components/provider-edit-flow.tsx
📜 Review details
🧰 Additional context used
🧠 Learnings (1)
📓 Common learnings
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.
🔇 Additional comments (2)
web/src/pages/providers/components/custom-config-step.tsx (1)

228-241: LGTM!

Error Cooldown 部分的布局重构清晰合理,flex 布局使开关控件与文本的对齐更加一致。

web/src/pages/providers/components/provider-edit-flow.tsx (1)

637-639: 布局处理正确

当 API Key 字段被隐藏时,网格布局从双列切换到单列,避免了空白区域。这是处理条件渲染时的正确布局策略。

@ymkiux
Copy link
Contributor

ymkiux commented Mar 17, 2026

@coderabbitai re-review !Stop making breaking changes, do a proper review!

@awsl233777
Copy link
Collaborator Author

继续修复

已按最新评论继续调整:编辑页在 excludeFromExporttrue 时,不再静默删除 API Key 区域,而是显示明确的占位说明。

本次改动

  • web/src/pages/providers/components/provider-edit-flow.tsx
    • 保留 API Key 区域的标题与占位说明
    • shouldShowApiKeyFieldfalse 时,显示只读提示文本,而不是直接移除整个区域
    • 同时恢复双列布局,使 Base URL / API Key 提示保持同级展示
  • web/src/locales/en.json
  • web/src/locales/zh.json
    • 新增 provider.apiKeyHiddenForExcluded 文案

测试结论

  • pnpm -C web exec tsc --noEmit

@coderabbitai re-review

!Stop making breaking changes, do a proper review!

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd "provider-edit-flow.tsx" --exec cat {}
echo "---FILE_BOUNDARY---"
fd "en.json" --search-path web/src/locales --exec grep -n "apiKeyHidden" {}
echo "---FILE_BOUNDARY---"
fd "zh.json" --search-path web/src/locales --exec grep -n "apiKeyHidden" {}
echo "---FILE_BOUNDARY---"
fd "custom-config-step.tsx" --exec cat {}

Length of output: 43047


@awsl233777 Re-review complete. Here is the updated analysis:


provider-edit-flow.tsx

✅ Previously 🔴 Breaking → Now Fixed: API key notice shown

The placeholder is correctly rendered when shouldShowApiKeyField is false:

<div className="p-3 bg-muted/50 border border-border rounded-lg text-xs text-muted-foreground">
  {t('provider.apiKeyHiddenForExcluded')}
</div>

The English copy is clear and actionable: users are told why the field is hidden and what to do. Both en.json and zh.json contain the key at line 1199. ✅

✅ Two-column layout restored

grid grid-cols-1 md:grid-cols-2 gap-6 is now unconditional — the notice occupies the right column correctly. ✅

✅ Save / Clone path: API key and mappings correctly preserved

  • formData.apiKey || provider.config?.custom?.apiKey || '' — existing key preserved on save. ✅
  • Clone mapping now passes all fields (providerType, priority, isEnabled, etc.). ✅

🟡 Residual UX limitation: excludeFromExport is not editable in the edit form

EditFormData has no excludeFromExport field, and handleSave hardcodes:

excludeFromExport: !!provider.excludeFromExport,

Once a provider is created with excludeFromExport: true, there is no way via the edit UI to reverse it and regain API key editing. The notice text does partially communicate this ("Disable that setting on creation"), but users who already created such a provider are at a dead end. This is a residual UX concern — not a data-loss bug, but worth noting.


custom-config-step.tsx

🟡 Still present: createModelMapping missing fields for template mappings

await createModelMapping.mutateAsync({
  scope: 'provider',
  providerID: provider.id,
  pattern: mapping.pattern,
  target: mapping.target,
  // missing: providerType, priority, isEnabled
});

Compare with the clone path in provider-edit-flow.tsx which now correctly passes all fields. Template mappings created during provider creation may default to isEnabled: false on the backend, causing them to be silently inactive.


Summary

Item Status
API key silently removed ✅ Fixed — informative notice shown
en.json / zh.json i18n key ✅ Both present
Two-column layout ✅ Restored
Save/clone preserves API key
Clone mapping fields complete ✅ Fixed
excludeFromExport not editable in edit form 🟡 Residual UX limitation
createModelMapping missing fields in custom-config-step.tsx 🟡 Still present

The 🔴 breaking change from the previous reviews has been resolved. The two remaining 🟡 items are lower severity — the createModelMapping one in particular is worth fixing to match the clone path behavior.


🧠 Learnings used
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd "provider-edit-flow.tsx" --exec cat {}
echo "---FILE_BOUNDARY---"
fd "custom-config-step.tsx" --exec cat {}

Length of output: 42711


@ymkiux Here is the updated review based on the current state of the code.


provider-edit-flow.tsx — Updated Assessment

✅ Previously flagged: "No visual feedback" — Now addressed

The current code correctly renders a label + informational placeholder when the API key field is hidden:

<div>
  <label className="text-sm font-medium text-foreground block mb-2">
    <div className="flex items-center gap-2">
      <Key size={14} />
      <span>{t('provider.apiKeyEdit')}</span>
    </div>
  </label>
  <div className="p-3 bg-muted/50 border border-border rounded-lg text-xs text-muted-foreground">
    {t('provider.apiKeyHiddenForExcluded')}
  </div>
</div>

The user sees the label and an explanation — not a silent gap. This resolves my earlier concern.

✅ Layout — Correct

The grid is always two columns; the second column renders either the key input or the placeholder. No empty column.

✅ Save/Clone — API key correctly preserved

Both handleSave and handleClone use formData.apiKey || provider.config?.custom?.apiKey || '', so the existing key is preserved. Clone mappings correctly copy all fields (providerType, priority, isEnabled, etc.).

🟡 Remaining design gap: excludeFromExport has no edit-form toggle

EditFormData does not include excludeFromExport, and handleSave always writes !!provider.excludeFromExport from the original prop. There is no switch in the edit UI to reverse it. This means:

  • A provider created with excludeFromExport: true will have its API key permanently inaccessible via the edit form.
  • A user cannot unset excludeFromExport through the edit form to regain key editing capability.

This is the PR's stated intent, but it's worth confirming it is a deliberate product decision and not an oversight.


custom-config-step.tsx — Updated Assessment

excludeFromExport section — Correct

Separated into its own independent section, switch binding and save path are both correct.

🟡 createModelMapping for template mappings omits providerType, priority, isEnabled

await createModelMapping.mutateAsync({
  scope: 'provider',
  providerID: provider.id,
  pattern: mapping.pattern,
  target: mapping.target,
  // providerType, priority, isEnabled not provided
});

These fields are TypeScript-optional, so there are no type errors. Whether this matters depends on backend defaults for isEnabled — if it defaults to false, template mappings created at provider-creation time would be disabled by default.


Summary:

Item Status
API key placeholder when hidden ✅ Fixed
Layout (no empty column) ✅ Correct
Save/clone preserves API key ✅ Correct
Clone model mappings copy all fields ✅ Correct
excludeFromExport section in custom-config-step ✅ Correct
excludeFromExport toggle absent from edit form 🟡 Design gap — intentional?
createModelMapping omits isEnabled at creation 🟡 Minor — depends on backend default

🧠 Learnings used
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.

Copy link

@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

♻️ Duplicate comments (1)
web/src/pages/providers/components/provider-edit-flow.tsx (1)

310-310: ⚠️ Potential issue | 🟠 Major

仍有行为回退:excludeFromExport 使 API Key 轮换能力不可用。

现在只是补了提示文案,但仍然完全阻断了编辑 API Key。excludeFromExport 是导出/备份语义,不应同时变成“禁止密钥轮换”的权限开关;这会让已开启该选项的 Provider 在编辑流里无法完成常见运维动作(密钥轮换)。建议至少保留可编辑输入(仅在导出层排除密钥),或在编辑页提供可逆的 excludeFromExport 控制。

Based on learnings: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.

Also applies to: 662-700

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

In `@web/src/pages/providers/components/provider-edit-flow.tsx` at line 310, The
current boolean shouldShowApiKeyField (used in provider-edit-flow.tsx) hides the
API Key input whenever provider.excludeFromExport is true, which incorrectly
blocks key rotation; change the behavior so the API Key input remains editable
regardless of excludeFromExport (i.e., do not gate visibility of the key field
on excludeFromExport), and instead keep excludeFromExport only as a metadata
flag used at export/backup time or surface it as a separate toggle (e.g., add an
explicit reversible control bound to provider.excludeFromExport) so
editing/rotating the API key (in the component handling the API key input and
functions that persist key changes) is always possible even when
excludeFromExport is set.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@web/src/pages/providers/components/provider-edit-flow.tsx`:
- Around line 678-683: The API key show/hide button currently uses
tabIndex={-1}, which removes it from keyboard focus; remove the tabIndex prop
from the button element so it remains reachable by keyboard users and add an
appropriate aria-label (e.g., referencing showApiKey state) to the button in the
provider-edit-flow component so screen reader users understand its purpose and
state.

---

Duplicate comments:
In `@web/src/pages/providers/components/provider-edit-flow.tsx`:
- Line 310: The current boolean shouldShowApiKeyField (used in
provider-edit-flow.tsx) hides the API Key input whenever
provider.excludeFromExport is true, which incorrectly blocks key rotation;
change the behavior so the API Key input remains editable regardless of
excludeFromExport (i.e., do not gate visibility of the key field on
excludeFromExport), and instead keep excludeFromExport only as a metadata flag
used at export/backup time or surface it as a separate toggle (e.g., add an
explicit reversible control bound to provider.excludeFromExport) so
editing/rotating the API key (in the component handling the API key input and
functions that persist key changes) is always possible even when
excludeFromExport is set.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 935331e1-d22c-40a6-a476-5c5465b479ed

📥 Commits

Reviewing files that changed from the base of the PR and between 5b18a0d and 79f25df.

📒 Files selected for processing (3)
  • web/src/locales/en.json
  • web/src/locales/zh.json
  • web/src/pages/providers/components/provider-edit-flow.tsx
📜 Review details
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: playwright
  • GitHub Check: e2e
🧰 Additional context used
🧠 Learnings (2)
📓 Common learnings
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.
📚 Learning: 2026-03-11T07:29:12.071Z
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.

Applied to files:

  • web/src/pages/providers/components/provider-edit-flow.tsx
🔇 Additional comments (2)
web/src/locales/en.json (1)

1199-1199: 文案新增与界面行为一致,认可此修改。

该提示文案能明确解释字段隐藏原因,避免“无提示消失”的困惑。

web/src/locales/zh.json (1)

1199-1199: 中文文案与英文语义对齐,修改合理。

提示信息清晰,能帮助用户理解为何当前不可编辑 API Key。

@awsl233777
Copy link
Collaborator Author

继续修复

已按最新评论继续调整为更安全的行为:excludeFromExport 不再阻断 API Key 轮换。

本次改动

  • web/src/pages/providers/components/provider-edit-flow.tsx
    • 恢复 API Key 输入框始终可编辑,不再因 excludeFromExport 隐藏或锁死
    • 当 provider 处于“从导出与备份中排除”状态时,在输入框下方显示说明提示
    • 移除 API Key 显隐按钮的 tabIndex={-1}
    • 为显隐按钮增加 aria-label,改善键盘与读屏可访问性
  • web/src/locales/en.json
  • web/src/locales/zh.json
    • 将提示文案调整为“仍可在此轮换密钥,只是不参与导出/备份”语义

测试结论

  • pnpm -C web exec tsc --noEmit

@coderabbitai re-review

!Stop making breaking changes, do a proper review!

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Tip

For best results, initiate chat on the files or code changes.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
fd "provider-edit-flow.tsx" --exec cat {}
echo "---FILE_BOUNDARY---"
fd "en.json" --search-path web/src/locales --exec cat {}
echo "---FILE_BOUNDARY---"
fd "zh.json" --search-path web/src/locales --exec cat {}
echo "---FILE_BOUNDARY---"
fd "custom-config-step.tsx" --exec cat {}

Length of output: 146643


@awsl233777 Re-review complete. Here is the final assessment:


provider-edit-flow.tsx — All Previous Issues Resolved ✅

✅ Previously 🔴 Breaking → Now Fully Fixed

The API key input is now always visible and editable, regardless of excludeFromExport. When provider.excludeFromExport is true, a contextual note appears below the input:

{provider.excludeFromExport && (
  <div className="mt-2 p-3 bg-muted/50 border border-border rounded-lg text-xs text-muted-foreground">
    {t('provider.apiKeyExcludedHint')}
  </div>
)}

This correctly decouples export-exclusion semantics from edit permissions. ✅

✅ i18n keys match and copy is accurate

Both en.json (apiKeyExcludedHint) and zh.json correctly communicate that the key can still be rotated — it simply won't appear in exports or backups. Keys align with the t('provider.apiKeyExcludedHint') call in the component. ✅

✅ Accessibility improvements correct

tabIndex={-1} removed and aria-label added to the show/hide toggle — both correct. ✅

✅ Layout, save, and clone paths all correct

Always two-column grid. Both handleSave and handleClone correctly preserve the existing API key. Clone mapping copies all fields. ✅


custom-config-step.tsx — One Remaining 🟡

🟡 createModelMapping still omits providerType, priority, isEnabled

await createModelMapping.mutateAsync({
  scope: 'provider',
  providerID: provider.id,
  pattern: mapping.pattern,
  target: mapping.target,
  // missing: providerType, priority, isEnabled
});

Compare with ProviderModelMappings (which passes providerType: 'custom', priority, and isEnabled: true) and the clone path in provider-edit-flow.tsx (which passes all fields). Template mappings created at provider-creation time may be silently inactive if the backend defaults isEnabled to false.


Summary

Item Status
API key always editable (breaking change resolved)
Informational note below input for excluded providers
en.json / zh.json i18n keys correct
Accessibility (aria-label, no tabIndex={-1})
Layout (always two-column)
Save/clone preserves API key
createModelMapping missing providerType, priority, isEnabled in custom-config-step.tsx 🟡 Minor

The 🔴 breaking change from earlier reviews is fully resolved. The design is now correct. Only the one 🟡 minor issue remains in custom-config-step.tsx.


🧠 Learnings used
Learnt from: ymkiux
Repo: awsl-project/maxx PR: 0
File: :0-0
Timestamp: 2026-03-11T07:29:12.071Z
Learning: Reviewer ymkiux (repo: awsl-project/maxx) requires strict attention to breaking changes in all PRs. Always thoroughly audit public API, interface, and behavioral contract changes — especially in sidebar/auth/layout components — before raising review comments. Do not flag superficial style issues; focus on correctness, regressions, and breaking changes.

@ymkiux ymkiux merged commit 479ff95 into main Mar 17, 2026
4 checks passed
@ymkiux ymkiux deleted the fix/hide-api-key-for-excluded-provider branch March 17, 2026 16:00
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