Skip to content

feat: add config GUIs for RFC-conformance fields missing them - #27

Merged
ntkrnl64 merged 1 commit into
mainfrom
feat/config-guis-rfc-features
Aug 29, 2026
Merged

feat: add config GUIs for RFC-conformance fields missing them#27
ntkrnl64 merged 1 commit into
mainfrom
feat/config-guis-rfc-features

Conversation

@ntkrnl64

@ntkrnl64 ntkrnl64 commented Aug 29, 2026

Copy link
Copy Markdown
Member

The RFC-conformance work (#26) wired several configurable fields through the backend but left two with no dashboard GUI:

security.txt (RFC 9116) — security_contact / security_policy_url were added to SiteConfig and the admin PATCH allowlist, but the admin settings page had no fields, so /.well-known/security.txt could not be enabled from the UI. Add a "Security disclosure" card to the General tab.

Per-app client auth (RFC 7591/7523) — token_endpoint_auth_method / jwks / jwks_uri (migration 0065) were settable only via Dynamic Client Registration; the apps API PATCH and App Detail did not expose them. Thread them through the apps PATCH handler (with DCR-matching validation) and safeApp, add them to the OAuthApp/CreateAppBody types, and surface a token endpoint auth-method dropdown plus jwks / jwks_uri inputs (shown for private_key_jwt) in App Detail settings.

i18n (en + zh) and docs (admin.md, oauth.md + zh) updated to match. Verified: tsc -b, eslint, and a Vite production build all pass.

Sourcery 总结

启用 security.txt 的仪表板和 API 配置,以及每个应用的 OAuth 客户端身份验证设置。

新功能:

  • 在“常规”选项卡中添加用于配置 RFC 9116 安全联系人和策略设置的控件。
  • 在应用设置 UI 和 API 中公开每个应用的 OAuth 令牌端点身份验证方法,以及 private_key_jwt 密钥来源。

增强功能:

  • 验证 OAuth 身份验证方法、JWKS 内容、JWKS URI 值,以及 private_key_jwt 客户端所需的密钥来源。
  • 更新英文和中文文档及翻译,以支持新的配置选项。

文档:

  • 使用英文和中文记录 security.txt 管理,以及 private_key_jwt 客户端的仪表板/API 配置。
Original summary in English

Summary by Sourcery

Enable dashboard and API configuration for security.txt and per-application OAuth client authentication settings.

New Features:

  • Add General-tab controls for configuring RFC 9116 security contact and policy settings.
  • Expose per-application OAuth token endpoint authentication methods and private_key_jwt key sources in the app settings UI and API.

Enhancements:

  • Validate OAuth authentication methods, JWKS content, JWKS URI values, and required key sources for private_key_jwt clients.
  • Update English and Chinese documentation and translations for the new configuration options.

Documentation:

  • Document security.txt administration and dashboard/API configuration for private_key_jwt clients in English and Chinese.

The RFC-conformance work (#26) wired several configurable fields through
the backend but left two with no dashboard GUI:

security.txt (RFC 9116) — security_contact / security_policy_url were
added to SiteConfig and the admin PATCH allowlist, but the admin settings
page had no fields, so /.well-known/security.txt could not be enabled from
the UI. Add a "Security disclosure" card to the General tab.

Per-app client auth (RFC 7591/7523) — token_endpoint_auth_method / jwks /
jwks_uri (migration 0065) were settable only via Dynamic Client
Registration; the apps API PATCH and App Detail did not expose them. Thread
them through the apps PATCH handler (with DCR-matching validation) and
safeApp, add them to the OAuthApp/CreateAppBody types, and surface a token
endpoint auth-method dropdown plus jwks / jwks_uri inputs (shown for
private_key_jwt) in App Detail settings.

i18n (en + zh) and docs (admin.md, oauth.md + zh) updated to match.
Verified: tsc -b, eslint, and a Vite production build all pass.
@ntkrnl64
ntkrnl64 merged commit c8af605 into main Aug 29, 2026
2 of 3 checks passed
@ntkrnl64
ntkrnl64 deleted the feat/config-guis-rfc-features branch August 29, 2026 19:28
@sourcery-ai

sourcery-ai Bot commented Aug 29, 2026

Copy link
Copy Markdown

审查者指南

完成 RFC 合规字段缺失的仪表板和 API 连接:管理员可以配置 RFC 9116 security.txt 元数据,应用所有者可以选择令牌端点身份验证方法,并管理带验证、持久化、本地化界面和更新文档的 private_key_jwt 密钥来源。

应用 private_key_jwt 配置的时序图

sequenceDiagram
    participant Owner as AppOwner
    participant UI as AppDetail
    participant API as AppsAPI
    participant DB as Database

    AppOwner->>AppDetail: Select private_key_jwt and enter jwks or jwks_uri
    AppDetail->>AppsAPI: PATCH /apps/:id
    AppsAPI->>AppsAPI: Validate token_endpoint_auth_method
    AppsAPI->>AppsAPI: Validate jwks or jwks_uri
    AppsAPI->>Database: UPDATE oauth_apps
    Database-->>AppsAPI: Updated app
    AppsAPI-->>AppDetail: safeApp with auth settings
    AppDetail-->>AppOwner: Show saved configuration
Loading

文件级变更

变更 详细信息 文件
添加用于配置 RFC 9116 安全披露元数据的仪表板控件。
  • 在 General 标签页中添加安全联系人和策略 URL 字段。
  • 将这些字段绑定到现有的 SiteConfig 设置,并将其标签、提示和描述进行本地化。
  • 记录这些设置如何启用并填充 security.txt。
src/pages/admin/AdminSettings.tsx
src/i18n/en.json
src/i18n/zh.json
docs/admin.md
docs/zh/admin.md
通过应用 API 和仪表板公开每个应用的 RFC 7591/7523 身份验证设置。
  • 扩展 OAuth 应用以及创建/更新负载类型,加入身份验证方法、内联 JWKS 和 JWKS URI 字段。
  • 验证受支持的身份验证方法、JWKS JSON 结构、HTTPS JWKS URI,并要求 private_key_jwt 提供密钥来源。
  • 在应用 PATCH 更新中持久化这些字段,并通过 safeApp 返回这些字段。
  • 在应用详情设置中添加身份验证方法下拉菜单,以及按条件显示的 private_key_jwt 密钥输入项。
  • 记录 private_key_jwt 的仪表板和 API 配置路径,并提供英文和中文翻译。
worker/routes/apps.ts
src/lib/api.ts
src/pages/apps/AppDetail.tsx
src/i18n/en.json
src/i18n/zh.json
docs/oauth.md
docs/zh/oauth.md

提示和命令

与 Sourcery 交互

  • 触发新的审查: 在拉取请求中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审查评论。
  • 根据审查评论生成 GitHub issue: 回复审查评论,请 Sourcery 根据该评论创建 issue。你也可以使用 @sourcery-ai issue 回复审查评论,以根据该评论创建 issue。
  • 生成拉取请求标题: 在拉取请求标题的任意位置写入 @sourcery-ai,即可随时生成标题。你也可以在拉取请求中评论 @sourcery-ai title,以随时生成或重新生成标题。
  • 生成拉取请求摘要: 在拉取请求正文的任意位置写入 @sourcery-ai summary,即可在指定位置随时生成 PR 摘要。你也可以在拉取请求中评论 @sourcery-ai summary,以随时生成或重新生成摘要。
  • 生成审查者指南: 在拉取请求中评论 @sourcery-ai guide,以随时生成或重新生成审查者指南。
  • 解决所有 Sourcery 评论: 在拉取请求中评论 @sourcery-ai resolve,以解决所有 Sourcery 评论。如果你已经处理了所有评论并不想再看到它们,这一功能会很有用。
  • 驳回所有 Sourcery 审查: 在拉取请求中评论 @sourcery-ai dismiss,以驳回所有现有的 Sourcery 审查。如果你想从头开始新的审查,这一功能尤其有用——别忘了评论 @sourcery-ai review 来触发新的审查!

自定义你的使用体验

访问你的仪表板来:

  • 启用或禁用审查功能,例如 Sourcery 生成的拉取请求摘要、审查者指南等。
  • 更改审查语言。
  • 添加、删除或编辑自定义审查说明。
  • 调整其他审查设置。

获取帮助

Original review guide in English

Reviewer's Guide

Completes the missing dashboard and API plumbing for RFC-conformance fields: administrators can configure RFC 9116 security.txt metadata, while app owners can select token endpoint authentication methods and manage private_key_jwt key sources with validation, persistence, localized UI, and updated documentation.

Sequence diagram for app private_key_jwt configuration

sequenceDiagram
    participant Owner as AppOwner
    participant UI as AppDetail
    participant API as AppsAPI
    participant DB as Database

    AppOwner->>AppDetail: Select private_key_jwt and enter jwks or jwks_uri
    AppDetail->>AppsAPI: PATCH /apps/:id
    AppsAPI->>AppsAPI: Validate token_endpoint_auth_method
    AppsAPI->>AppsAPI: Validate jwks or jwks_uri
    AppsAPI->>Database: UPDATE oauth_apps
    Database-->>AppsAPI: Updated app
    AppsAPI-->>AppDetail: safeApp with auth settings
    AppDetail-->>AppOwner: Show saved configuration
Loading

File-Level Changes

Change Details Files
Add dashboard controls for configuring RFC 9116 security disclosure metadata.
  • Add General-tab fields for security contact and policy URL.
  • Bind the fields to existing SiteConfig settings and localize their labels, hints, and description.
  • Document how these settings enable and populate security.txt.
src/pages/admin/AdminSettings.tsx
src/i18n/en.json
src/i18n/zh.json
docs/admin.md
docs/zh/admin.md
Expose per-application RFC 7591/7523 authentication settings through the app API and dashboard.
  • Extend OAuth app and create/update payload types with auth method, inline JWKS, and JWKS URI fields.
  • Validate supported auth methods, JWKS JSON structure, HTTPS JWKS URIs, and require a key source for private_key_jwt.
  • Persist the fields in app PATCH updates and return them through safeApp.
  • Add an auth-method dropdown and conditional private_key_jwt key inputs to App Detail settings.
  • Document dashboard and API configuration paths for private_key_jwt, with English and Chinese translations.
worker/routes/apps.ts
src/lib/api.ts
src/pages/apps/AppDetail.tsx
src/i18n/en.json
src/i18n/zh.json
docs/oauth.md
docs/zh/oauth.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

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

你好——我发现了 2 个问题

给 AI 代理的提示
请处理本次代码审查中的评论:

## 单条评论

### 评论 1
<location path="src/pages/apps/AppDetail.tsx" line_range="1478" />
<code_context>
+                <Option value="client_secret_post">client_secret_post</Option>
+                <Option value="private_key_jwt">private_key_jwt</Option>
+                <Option value="none">none</Option>
+              </Dropdown>
+            </Field>
+            {form.token_endpoint_auth_method === "private_key_jwt" && (
</code_context>
<issue_to_address>
**issue (bug_risk):** 在 App Detail 中选择 `none` 会将 `token_endpoint_auth_method = "none"` 保存下来,但令牌认证路径仍会对除 `private_key_jwt` 之外的所有方法调用 `clientSecretValid`。因此,机密客户端仍然需要其客户端密钥,而不是像 RFC 7591 对 `none` 的要求那样,在不进行客户端认证的情况下被接受。

**Triggers:** 当管理员为机密应用选择 `none`,但没有同时将应用设为公共应用时。

**Suggested fix:** 让令牌认证遵循已配置的方法,包括接受针对 `none` 的仅包含客户端 ID 的请求,或者将 `none` 与应用的公共客户端设置进行同步/校验。
</issue_to_address>

### 评论 2
<location path="src/pages/apps/AppDetail.tsx" line_range="1472-1478" />
<code_context>
+                }
+              >
+                <Option value="">{t("apps.authMethodDefault")}</Option>
+                <Option value="client_secret_basic">
+                  client_secret_basic
+                </Option>
+                <Option value="client_secret_post">client_secret_post</Option>
+                <Option value="private_key_jwt">private_key_jwt</Option>
+                <Option value="none">none</Option>
+              </Dropdown>
+            </Field>
+            {form.token_endpoint_auth_method === "private_key_jwt" && (
</code_context>
<issue_to_address>
**issue (bug_risk):** UI 将 `client_secret_basic``client_secret_post``none` 展示为不同的认证方法,但后端并未强制执行这些区别:对于所有非私钥方法,同一认证流程既接受 Basic 凭据,也接受 `client_id`/`client_secret` 表单参数。因此,存储的方法和发现元数据可能声明一种方法,而令牌、PAR 及相关端点却接受另一种方法。

**Triggers:** 当客户端被配置为使用 `client_secret_basic``client_secret_post``none`,却使用了不同的凭据传输方式时。

**Suggested fix:** 根据存储的方法分支处理认证,并拒绝通过未配置的传输方式提交的凭据。
</issue_to_address>

Sourcery 对开源项目免费——如果您喜欢我们的审查结果,请考虑分享 ✨
帮助我变得更有用!请在每条评论上点击 👍 或 👎,我会利用反馈来改进审查结果。
Original comment in English

Hey - I've found 2 issues

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location path="src/pages/apps/AppDetail.tsx" line_range="1478" />
<code_context>
+                <Option value="client_secret_post">client_secret_post</Option>
+                <Option value="private_key_jwt">private_key_jwt</Option>
+                <Option value="none">none</Option>
+              </Dropdown>
+            </Field>
+            {form.token_endpoint_auth_method === "private_key_jwt" && (
</code_context>
<issue_to_address>
**issue (bug_risk):** Selecting `none` in App Detail stores `token_endpoint_auth_method = "none"`, but the token authentication path still calls `clientSecretValid` for every method except `private_key_jwt`. Confidential clients therefore continue to require their client secret instead of being accepted without client authentication as RFC 7591 `none` requires.

**Triggers:** When an administrator selects `none` for a confidential app without also making the app public.

**Suggested fix:** Make token authentication honor the configured method, including accepting a client-id-only request for `none`, or synchronize/validate `none` with the app's public-client setting.
</issue_to_address>

### Comment 2
<location path="src/pages/apps/AppDetail.tsx" line_range="1472-1478" />
<code_context>
+                }
+              >
+                <Option value="">{t("apps.authMethodDefault")}</Option>
+                <Option value="client_secret_basic">
+                  client_secret_basic
+                </Option>
+                <Option value="client_secret_post">client_secret_post</Option>
+                <Option value="private_key_jwt">private_key_jwt</Option>
+                <Option value="none">none</Option>
+              </Dropdown>
+            </Field>
+            {form.token_endpoint_auth_method === "private_key_jwt" && (
</code_context>
<issue_to_address>
**issue (bug_risk):** The UI presents `client_secret_basic`, `client_secret_post`, and `none` as distinct authentication methods, but the backend does not enforce those distinctions: the same authentication flow accepts either Basic credentials or `client_id`/`client_secret` form parameters for every non-private-key method. The stored method and discovery metadata can therefore claim one method while the token, PAR, and related endpoints accept another.

**Triggers:** When a client is configured with `client_secret_basic`, `client_secret_post`, or `none` and uses a different credential transport.

**Suggested fix:** Branch authentication by the stored method and reject credentials presented through an unconfigured transport.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

<Option value="client_secret_post">client_secret_post</Option>
<Option value="private_key_jwt">private_key_jwt</Option>
<Option value="none">none</Option>
</Dropdown>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): 在 App Detail 中选择 none 会将 token_endpoint_auth_method = "none" 保存下来,但令牌认证路径仍会对除 private_key_jwt 之外的所有方法调用 clientSecretValid。因此,机密客户端仍然需要其客户端密钥,而不是像 RFC 7591 对 none 的要求那样,在不进行客户端认证的情况下被接受。

Triggers: 当管理员为机密应用选择 none,但没有同时将应用设为公共应用时。

Suggested fix: 让令牌认证遵循已配置的方法,包括接受针对 none 的仅包含客户端 ID 的请求,或者将 none 与应用的公共客户端设置进行同步/校验。

Original comment in English

issue (bug_risk): Selecting none in App Detail stores token_endpoint_auth_method = "none", but the token authentication path still calls clientSecretValid for every method except private_key_jwt. Confidential clients therefore continue to require their client secret instead of being accepted without client authentication as RFC 7591 none requires.

Triggers: When an administrator selects none for a confidential app without also making the app public.

Suggested fix: Make token authentication honor the configured method, including accepting a client-id-only request for none, or synchronize/validate none with the app's public-client setting.

Comment on lines +1472 to +1478
<Option value="client_secret_basic">
client_secret_basic
</Option>
<Option value="client_secret_post">client_secret_post</Option>
<Option value="private_key_jwt">private_key_jwt</Option>
<Option value="none">none</Option>
</Dropdown>

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

issue (bug_risk): UI 将 client_secret_basicclient_secret_postnone 展示为不同的认证方法,但后端并未强制执行这些区别:对于所有非私钥方法,同一认证流程既接受 Basic 凭据,也接受 client_id/client_secret 表单参数。因此,存储的方法和发现元数据可能声明一种方法,而令牌、PAR 及相关端点却接受另一种方法。

Triggers: 当客户端被配置为使用 client_secret_basicclient_secret_postnone,却使用了不同的凭据传输方式时。

Suggested fix: 根据存储的方法分支处理认证,并拒绝通过未配置的传输方式提交的凭据。

Original comment in English

issue (bug_risk): The UI presents client_secret_basic, client_secret_post, and none as distinct authentication methods, but the backend does not enforce those distinctions: the same authentication flow accepts either Basic credentials or client_id/client_secret form parameters for every non-private-key method. The stored method and discovery metadata can therefore claim one method while the token, PAR, and related endpoints accept another.

Triggers: When a client is configured with client_secret_basic, client_secret_post, or none and uses a different credential transport.

Suggested fix: Branch authentication by the stored method and reject credentials presented through an unconfigured transport.

@github-actions

Copy link
Copy Markdown

Preview deployed: https://prism-preview.siiway.workers.dev (shared preview Worker + database, so the newest PR deploy is what is live there).

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.

1 participant